| public static primaryModel ( ?\ | ||
| $value | ?\ |
|
public function primaryModel(?ActiveRecordInterface $value): static
{
$this->primaryModel = $value;
return $this;
}
| Inheritance | Yiisoft\ |
|---|---|
| Implements | Yiisoft\ |
Represents a db query associated with an Active Record class.
An ActiveQuery can be a normal query or be used in a relational context.
ActiveQuery instances are usually created by {@see \
Relational queries are created by {@see \
ActiveQuery mainly provides the following methods to retrieve the query results:
Because ActiveQuery extends from {@see \
ActiveQuery also provides the following more query options:
These options can be configured using methods of the same name. For example:
$customerQuery = Customer::query();
$query = $customerQuery->with('orders')->asArray()->all();
In relational context, ActiveQuery represents a relation between two Active Record classes.
Relational ActiveQuery instances are usually created by calling {@see \
A relation is specified by {@see \
If a relation involves a junction table, it may be specified by {@see \
These methods may only be called in a relational context. The same is true for
{@see \
| Method | Description | Defined By |
|---|---|---|
| createModels() | Converts found rows into model instances. | Yiisoft\ |
| getPrimaryTableName() | Yiisoft\ |
|
| index() | Yiisoft\ |
|
| queryScalar() | Queries a scalar value by setting {@see Query::select()} first. | Yiisoft\ |
Clones internal objects
| public mixed __clone ( ) |
public function __clone()
{
/// Make a clone of "via" object so that the same query object can be reused multiple times.
if (is_object($this->via)) {
$this->via = clone $this->via;
} elseif (is_array($this->via)) {
$this->via = [$this->via[0], clone $this->via[1], $this->via[2]];
}
}
| public mixed __construct ( Yiisoft\ | ||
| $modelClass | Yiisoft\ |
|
final public function __construct(
ActiveRecordInterface|string $modelClass,
) {
$this->model = $modelClass instanceof ActiveRecordInterface
? $modelClass
: new $modelClass();
parent::__construct($this->model->db());
}
| public static alias ( string $alias ) | ||
| $alias | string | |
public function alias(string $alias): static
{
if (count($this->from) < 2) {
[$tableName] = TableNameAndAliasResolver::resolve($this);
$this->from = [$alias => $tableName];
} else {
$tableName = $this->getPrimaryTableName();
foreach ($this->from as $key => $table) {
if ($table === $tableName) {
unset($this->from[$key]);
$this->from[$alias] = $tableName;
}
}
}
return $this;
}
| public static andOn ( array|\ | ||
| $condition | array|\ |
|
| $params | array | |
public function andOn(array|ExpressionInterface|string $condition, array $params = []): static
{
$this->on = $this->on === null
? $condition
: ['and', $this->on, $condition];
$this->addParams($params);
return $this;
}
| public static asArray ( ?bool $value = true ) | ||
| $value | ?bool | |
public function asArray(?bool $value = true): static
{
$this->asArray = $value;
return $this;
}
| public \ | ||
| $batchSize | integer | |
public function batch(int $batchSize = 100): BatchQueryResultInterface
{
/**
* @var Closure(non-empty-array<array>):non-empty-array<object> $callback
*/
$callback = $this->index(...);
return parent::batch($batchSize)->indexBy(null)->resultCallback($callback);
}
Creates a db command that can be used to execute this query.
| public \ | ||
| throws | \ |
|
|---|---|---|
public function createCommand(): CommandInterface
{
if ($this->sql === null) {
[$sql, $params] = $this->db->getQueryBuilder()->build($this);
} else {
$sql = $this->sql;
$params = $this->params;
}
return $this->db->createCommand($sql, $params);
}
Converts found rows into model instances.
| protected Yiisoft\ | ||
| $rows | array[] |
The rows to be converted. |
| return | Yiisoft\ |
The model instances. |
|---|---|---|
protected function createModels(array $rows): array
{
if ($this->asArray) {
$model = $this->getModel();
return array_map(
static fn(array $row) => Typecaster::cast($row, $model),
$rows,
);
}
if ($this->resultCallback !== null) {
$rows = ($this->resultCallback)($rows);
if ($rows[0] instanceof ActiveRecordInterface) {
/** @psalm-var non-empty-list<ActiveRecordInterface> */
return $rows;
}
}
/** @var non-empty-list<array<string, mixed>> $rows */
return array_map(
fn(array $row) => $this->getModel()->populateRecord($row),
$rows,
);
}
| public \ |
public function each(): DataReaderInterface
{
/** @psalm-suppress InvalidArgument */
return $this->createCommand()
->query()
->indexBy($this->indexBy)
->resultCallback($this->populateOne(...));
}
| public array|\ | ||
| $values | array|float|integer|string | |
public function findByPk(array|float|int|string $values): array|ActiveRecordInterface|null
{
$values = (array) $values;
$model = $this->getModel();
$primaryKey = $model->primaryKey();
if (empty($primaryKey)) {
throw new InvalidConfigException($model::class . ' must have a primary key.');
}
if (count($primaryKey) !== count($values)) {
throw new InvalidArgumentException(
'The primary key has ' . count($primaryKey) . ' columns, but ' . count($values) . ' values are passed.',
);
}
if (!empty($this->getJoins()) || !empty($this->getJoinsWith())) {
$tableName = $model->tableName();
foreach ($primaryKey as &$pk) {
$pk = "$tableName.$pk";
}
}
return (clone $this)->andWhere(array_combine($primaryKey, $values))->one();
}
| public ?string getInverseOf ( ) |
public function getInverseOf(): ?string
{
return $this->inverseOf;
}
| public Yiisoft\ |
public function getModel(): ActiveRecordInterface
{
return clone $this->model;
}
| public array|\ |
public function getOn(): array|ExpressionInterface|string|null
{
return $this->on;
}
| public ?\ |
public function getPrimaryModel(): ?ActiveRecordInterface
{
return $this->primaryModel;
}
| protected string getPrimaryTableName ( ) |
protected function getPrimaryTableName(): string
{
return $this->getModel()->tableName();
}
| public array getTablesUsedInFrom ( ) |
public function getTablesUsedInFrom(): array
{
if (empty($this->from)) {
return $this->db->getQuoter()->cleanUpTableNames([$this->getPrimaryTableName()]);
}
return parent::getTablesUsedInFrom();
}
| public array|\ |
public function getVia(): array|ActiveQueryInterface|null
{
return $this->via;
}
| protected array index ( array $rows ) | ||
| $rows | array | |
protected function index(array $rows): array
{
return ArArrayHelper::index($this->populate($rows), $this->indexBy);
}
| public static innerJoinWith ( array|string $with, array|boolean $eagerLoading = true ) | ||
| $with | array|string | |
| $eagerLoading | array|boolean | |
public function innerJoinWith(array|string $with, array|bool $eagerLoading = true): static
{
return $this->joinWith($with, $eagerLoading, 'INNER JOIN');
}
| public static inverseOf ( string $relationName ) | ||
| $relationName | string | |
public function inverseOf(string $relationName): static
{
$this->inverseOf = $relationName;
return $this;
}
| public static joinWith ( array|string $with, array|boolean $eagerLoading = true, array|string $joinType = 'LEFT JOIN' ) | ||
| $with | array|string | |
| $eagerLoading | array|boolean | |
| $joinType | array|string | |
public function joinWith(
array|string $with,
array|bool $eagerLoading = true,
array|string $joinType = 'LEFT JOIN',
): static {
$relations = [];
foreach ((array) $with as $name => $callback) {
if (is_int($name)) {
$name = $callback;
$callback = null;
}
/** @var string $name */
if (preg_match('/^(.*?)(?:\s+AS\s+|\s+)(\w+)$/i' , $name, $matches)) {
/** The relation is defined with an alias, adjust callback to apply alias */
[, $relation, $alias] = $matches;
$name = $relation;
$callback = static function (ActiveQueryInterface $query) use ($callback, $alias): void {
$query->alias($alias);
if ($callback !== null) {
$callback($query);
}
};
}
if ($callback === null) {
$relations[] = $name;
} else {
$relations[$name] = $callback;
}
}
$this->joinsWith[] = new JoinWith($relations, $eagerLoading, $joinType);
return $this;
}
| public static link ( array $value ) | ||
| $value | array | |
public function link(array $value): static
{
$this->link = $value;
return $this;
}
| public static multiple ( boolean $value ) | ||
| $value | boolean | |
public function multiple(bool $value): static
{
$this->multiple = $value;
return $this;
}
| public static on ( array|\ | ||
| $condition | array|\ |
|
| $params | array | |
public function on(array|ExpressionInterface|string $condition, array $params = []): static
{
$this->on = $condition;
$this->addParams($params);
return $this;
}
| public array|\ |
public function one(): array|ActiveRecordInterface|null
{
if ($this->shouldEmulateExecution()) {
return null;
}
$row = $this->createCommand()->queryOne();
if ($row === null) {
return null;
}
return $this->populateOne($row);
}
| public static orOn ( array|\ | ||
| $condition | array|\ |
|
| $params | array | |
public function orOn(array|ExpressionInterface|string $condition, array $params = []): static
{
$this->on = $this->on === null
? $condition
: ['or', $this->on, $condition];
$this->addParams($params);
return $this;
}
| public array populate ( array $rows ) | ||
| $rows | array | |
public function populate(array $rows): array
{
if (empty($rows)) {
return [];
}
if (!empty($this->joins) && $this->indexBy === null) {
$rows = $this->removeDuplicatedRows($rows);
}
$models = $this->createModels($rows);
if (!empty($this->with)) {
$this->findWith($this->with, $models);
}
$this->addInverseRelations($models);
return $models;
}
| public array populateRelation ( string $name, array &$primaryModels ) | ||
| $name | string | |
| $primaryModels | array | |
public function populateRelation(string $name, array &$primaryModels): array
{
return RelationPopulator::populate($this, $name, $primaryModels);
}
| public \ | ||
| $builder | \ |
|
| throws | \ |
|
|---|---|---|
| throws | \ |
|
| throws | \ |
|
| throws | \ |
|
| throws | Throwable | |
| throws | \ |
|
public function prepare(QueryBuilderInterface $builder): QueryInterface
{
/**
* NOTE: Because the same ActiveQuery may be used to build different SQL statements, one for count query, the
* other for row data query, it is important to make sure the same ActiveQuery can be used to build SQL
* statements many times.
*/
if (!empty($this->joinsWith)) {
JoinsWithBuilder::build($this);
/**
* Clean it up to avoid issue @link https://github.com/yiisoft/yii2/issues/2687
*/
$this->joinsWith = [];
}
if (empty($this->getFrom())) {
$this->from = [$this->getPrimaryTableName()];
}
if (empty($this->getSelect()) && !empty($this->getJoins())) {
[, $alias] = TableNameAndAliasResolver::resolve($this);
$this->select(["$alias.*"]);
}
if ($this->primaryModel === null) {
$query = $this->createInstance();
} else {
$where = $this->getWhere();
if ($this->via instanceof ActiveQueryInterface) {
$viaModels = JunctionRowsFinder::find($this->via, [$this->primaryModel]);
ModelRelationFilter::apply($this, $viaModels);
} elseif (is_array($this->via)) {
[$viaName, $viaQuery, $viaCallableUsed] = $this->via;
if ($viaQuery->isMultiple()) {
if ($viaCallableUsed) {
$viaModels = $viaQuery->all();
} elseif ($this->primaryModel->isRelationPopulated($viaName)) {
/** @var ActiveRecordInterface[]|array[] $viaModels */
$viaModels = $this->primaryModel->relation($viaName);
} else {
$viaModels = $viaQuery->all();
$this->primaryModel->populateRelation($viaName, $viaModels);
}
} else {
if ($viaCallableUsed) {
$model = $viaQuery->one();
} elseif ($this->primaryModel->isRelationPopulated($viaName)) {
$model = $this->primaryModel->relation($viaName);
} else {
$model = $viaQuery->one();
$this->primaryModel->populateRelation($viaName, $model);
}
$viaModels = $model === null ? [] : [$model];
}
ModelRelationFilter::apply($this, $viaModels);
} else {
ModelRelationFilter::apply($this, [$this->primaryModel]);
}
$query = $this->createInstance();
$this->setWhere($where);
}
if (!empty($this->on)) {
$query->andWhere($this->on);
}
return $query;
}
| public static primaryModel ( ?\ | ||
| $value | ?\ |
|
public function primaryModel(?ActiveRecordInterface $value): static
{
$this->primaryModel = $value;
return $this;
}
Queries a scalar value by setting {@see Query::select()} first.
Restores the value of select to make this query reusable.
| protected bool|string|int|float|null queryScalar ( \ | ||
| $selectExpression | \ |
The expression to be selected. |
| throws | \ |
|
|---|---|---|
| throws | InvalidArgumentException | |
| throws | \ |
|
| throws | \ |
|
| throws | Throwable | |
protected function queryScalar(string|ExpressionInterface $selectExpression): bool|string|int|float|null
{
if ($this->sql === null) {
return parent::queryScalar($selectExpression);
}
$command = (new Query($this->db))->select([$selectExpression])
->from(['c' => "($this->sql)"])
->params($this->params)
->createCommand();
return $command->queryScalar();
}
| public static resetWith ( ) |
public function resetWith(): static
{
$this->with = [];
$this->joinsWith = array_map(
static fn(JoinWith $joinWith) => $joinWith->withoutEagerLoading(),
$this->joinsWith,
);
return $this;
}
| public static sql ( ?string $value ) | ||
| $value | ?string | |
public function sql(?string $value): static
{
$this->sql = $value;
return $this;
}
| public static via ( string $relationName, ?callable $callable = null ) | ||
| $relationName | string | |
| $callable | ?callable | |
public function via(string $relationName, ?callable $callable = null): static
{
if ($this->primaryModel === null) {
throw new InvalidConfigException('Setting via is only supported for relational queries.');
}
$relation = $this->primaryModel->relationQuery($relationName);
$callableUsed = $callable !== null;
$this->via = [$relationName, $relation, $callableUsed];
if ($callableUsed) {
$callable($relation);
}
return $this;
}
| public static viaTable ( string $tableName, array $link, ?callable $callable = null ) | ||
| $tableName | string | |
| $link | array | |
| $callable | ?callable | |
public function viaTable(string $tableName, array $link, ?callable $callable = null): static
{
$model = $this->primaryModel ?? $this->model;
$relation = (new static($model))
->from([$tableName])
->link($link)
->multiple(true)
->asArray();
$this->via = $relation;
if ($callable !== null) {
$callable($relation);
}
return $this;
}
| public static with ( array|string $with ) | ||
| $with | array|string | |
public function with(array|string ...$with): static
{
if (isset($with[0]) && is_array($with[0])) {
/// the parameter is given as an array
$with = $with[0];
}
if (empty($this->with)) {
$this->with = $with;
} elseif (!empty($with)) {
foreach ($with as $name => $value) {
if (is_int($name)) {
// repeating relation is fine as `normalizeRelations()` handle it well
$this->with[] = $value;
} else {
$this->with[$name] = $value;
}
}
}
return $this;
}
User Contributed Notes
Leave a comment
Join the conversation to share a note.