0 关注者

特质 yii\db\ActiveRelationTrait

由以下实现yii\db\ActiveQuery
自版本起可用2.0
源代码 https://github.com/yiisoft/yii2/blob/master/framework/db/ActiveRelationTrait.php

ActiveRelationTrait 实现活动记录关系查询的通用方法和属性。

公共属性

隐藏继承的属性

属性 类型 描述 定义于
$inverseOf string 此关系的逆关系的名称。例如,一个订单有一个客户,这意味着“客户”关系的逆关系是“订单”,而“订单”关系的逆关系是“客户”。如果设置了此属性,则主记录将通过指定的关系进行引用。例如,$customer->orders[0]->customer$customer 将是同一个对象,访问订单的客户不会触发新的数据库查询。此属性仅在关系上下文中使用。 yii\db\ActiveRelationTrait
$modelClass yii\db\ActiveRecord yii\db\ActiveRelationTrait
$multiple boolean 此查询是否表示与多个记录的关系。此属性仅在关系上下文中使用。如果为真,则此关系将使用 all() 将所有查询结果填充到 AR 实例中。如果为假,则仅使用 one() 检索结果的第一行。 yii\db\ActiveRelationTrait
$primaryModel yii\db\ActiveRecord 关系查询的主模型。这仅用于具有动态查询选项的延迟加载。 yii\db\ActiveRelationTrait
$via array|object 与连接表关联的查询。 yii\db\ActiveRelationTrait

公共方法

隐藏继承的方法

方法 描述 定义于
__clone() 克隆内部对象。 yii\db\ActiveRelationTrait
all() 有关更多信息,请参阅 yii\db\ActiveQueryInterface::all() yii\db\ActiveRelationTrait
findFor() 查找指定主记录的相关记录。 yii\db\ActiveRelationTrait
inverseOf() 设置此关系的逆关系的名称。 yii\db\ActiveRelationTrait
one() 有关更多信息,请参阅 yii\db\ActiveQueryInterface::one() yii\db\ActiveRelationTrait
populateRelation() 查找相关记录并将其填充到主模型中。 yii\db\ActiveRelationTrait
via() 指定与连接表关联的关系。请调用 via() 设置此属性,而不是直接设置它。此属性仅在关系上下文中使用。 yii\db\ActiveRelationTrait

属性详细信息

隐藏继承的属性

$inverseOf 公共属性

此关系的逆关系的名称。例如,一个订单有一个客户,这意味着“客户”关系的逆关系是“订单”,而“订单”关系的逆关系是“客户”。如果设置了此属性,则主记录将通过指定的关系进行引用。例如,$customer->orders[0]->customer$customer 将是同一个对象,访问订单的客户不会触发新的数据库查询。此属性仅在关系上下文中使用。

另请参阅 inverseOf()

public string $inverseOf null
$modelClass 公共属性
$multiple 公共属性

此查询是否表示与多个记录的关系。此属性仅在关系上下文中使用。如果为真,则此关系将使用 all() 将所有查询结果填充到 AR 实例中。如果为假,则仅使用 one() 检索结果的第一行。

public boolean $multiple null
$primaryModel 公共属性

关系查询的主模型。这仅用于具有动态查询选项的延迟加载。

$via 公共属性

与连接表关联的查询。请调用 via() 设置此属性,而不是直接设置它。此属性仅在关系上下文中使用。

另请参阅 via()

public array|object $via null

方法详细信息

隐藏继承的方法

__clone() 公共方法

克隆内部对象。

public void __clone ( )

                public function __clone()
{
    parent::__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]];
    }
}

            
all() 公共方法

有关更多信息,请参阅 yii\db\ActiveQueryInterface::all()

public yii\db\ActiveRecordInterface[] all ( $db )
$db
返回 yii\db\ActiveRecordInterface[]
findFor() 公共方法

查找指定主记录的相关记录。

当延迟访问 ActiveRecord 的关系时,会调用此方法。

public mixed findFor ( $name, $model )
$name string

关系名称

$model yii\db\ActiveRecordInterface|yii\db\BaseActiveRecord

主模型

返回 mixed

相关记录

抛出 yii\base\InvalidArgumentException

如果关系无效

                public function findFor($name, $model)
{
    if (method_exists($model, 'get' . $name)) {
        $method = new \ReflectionMethod($model, 'get' . $name);
        $realName = lcfirst(substr($method->getName(), 3));
        if ($realName !== $name) {
            throw new InvalidArgumentException('Relation names are case sensitive. ' . get_class($model) . " has a relation named \"$realName\" instead of \"$name\".");
        }
    }
    return $this->multiple ? $this->all() : $this->one();
}

            
inverseOf() 公共方法

设置此关系的逆关系的名称。

例如,一个客户有订单,这意味着 "订单" 关系的逆关系是 "客户"。如果设置了此属性,主记录将通过指定的关系进行引用。例如,$customer->orders[0]->customer$customer 将是同一个对象,访问订单的客户将不会触发新的数据库查询。

yii\db\ActiveRecord 类中声明关系时使用此方法,例如在 Customer 模型中

public function getOrders()
{
    return $this->hasMany(Order::class, ['customer_id' => 'id'])->inverseOf('customer');
}

这也可能用于 Order 模型,但要谨慎

public function getCustomer()
{
    return $this->hasOne(Customer::class, ['id' => 'customer_id'])->inverseOf('orders');
}

在这种情况下,结果将取决于订单的加载方式。假设客户有几个订单。如果只加载了一个订单

$orders = Order::find()->where(['id' => 1])->all();
$customerOrders = $orders[0]->customer->orders;

变量 $customerOrders 将只包含一个订单。如果订单是像这样加载的

$orders = Order::find()->with('customer')->where(['customer_id' => 1])->all();
$customerOrders = $orders[0]->customer->orders;

变量 $customerOrders 将包含客户的所有订单。

public $this inverseOf ( $relationName )
$relationName string

此关系的逆关系的名称。例如,一个订单有一个客户,这意味着“客户”关系的逆关系是“订单”,而“订单”关系的逆关系是“客户”。如果设置了此属性,则主记录将通过指定的关系进行引用。例如,$customer->orders[0]->customer$customer 将是同一个对象,访问订单的客户不会触发新的数据库查询。此属性仅在关系上下文中使用。

返回 $this

关系对象本身。

                public function inverseOf($relationName)
{
    $this->inverseOf = $relationName;
    return $this;
}

            
one() 公共方法

有关更多信息,请参阅 yii\db\ActiveQueryInterface::one()

public yii\db\ActiveRecordInterface|array|null one ( $db )
$db
返回 yii\db\ActiveRecordInterface|array|null
populateRelation() 公共方法

查找相关记录并将其填充到主模型中。

public array populateRelation ( $name, &$primaryModels )
$name string

关系名称

$primaryModels array

主模型

返回 array

相关模型

抛出 yii\base\InvalidConfigException

如果 $link 无效

                public function populateRelation($name, &$primaryModels)
{
    if (!is_array($this->link)) {
        throw new InvalidConfigException('Invalid link: it must be an array of key-value pairs.');
    }
    if ($this->via instanceof self) {
        // via junction table
        /* @var $viaQuery ActiveRelationTrait */
        $viaQuery = $this->via;
        $viaModels = $viaQuery->findJunctionRows($primaryModels);
        $this->filterByModels($viaModels);
    } elseif (is_array($this->via)) {
        // via relation
        /* @var $viaQuery ActiveRelationTrait|ActiveQueryTrait */
        list($viaName, $viaQuery) = $this->via;
        if ($viaQuery->asArray === null) {
            // inherit asArray from primary query
            $viaQuery->asArray($this->asArray);
        }
        $viaQuery->primaryModel = null;
        $viaModels = array_filter($viaQuery->populateRelation($viaName, $primaryModels));
        $this->filterByModels($viaModels);
    } else {
        $this->filterByModels($primaryModels);
    }
    if (!$this->multiple && count($primaryModels) === 1) {
        $model = $this->one();
        $primaryModel = reset($primaryModels);
        if ($primaryModel instanceof ActiveRecordInterface) {
            $primaryModel->populateRelation($name, $model);
        } else {
            $primaryModels[key($primaryModels)][$name] = $model;
        }
        if ($this->inverseOf !== null) {
            $this->populateInverseRelation($primaryModels, [$model], $name, $this->inverseOf);
        }
        return [$model];
    }
    // https://github.com/yiisoft/yii2/issues/3197
    // delay indexing related models after buckets are built
    $indexBy = $this->indexBy;
    $this->indexBy = null;
    $models = $this->all();
    if (isset($viaModels, $viaQuery)) {
        $buckets = $this->buildBuckets($models, $this->link, $viaModels, $viaQuery);
    } else {
        $buckets = $this->buildBuckets($models, $this->link);
    }
    $this->indexBy = $indexBy;
    if ($this->indexBy !== null && $this->multiple) {
        $buckets = $this->indexBuckets($buckets, $this->indexBy);
    }
    $link = array_values($this->link);
    if (isset($viaQuery)) {
        $deepViaQuery = $viaQuery;
        while ($deepViaQuery->via) {
            $deepViaQuery = is_array($deepViaQuery->via) ? $deepViaQuery->via[1] : $deepViaQuery->via;
        };
        $link = array_values($deepViaQuery->link);
    }
    foreach ($primaryModels as $i => $primaryModel) {
        $keys = null;
        if ($this->multiple && count($link) === 1) {
            $primaryModelKey = reset($link);
            $keys = isset($primaryModel[$primaryModelKey]) ? $primaryModel[$primaryModelKey] : null;
        }
        if (is_array($keys)) {
            $value = [];
            foreach ($keys as $key) {
                $key = $this->normalizeModelKey($key);
                if (isset($buckets[$key])) {
                    if ($this->indexBy !== null) {
                        // if indexBy is set, array_merge will cause renumbering of numeric array
                        foreach ($buckets[$key] as $bucketKey => $bucketValue) {
                            $value[$bucketKey] = $bucketValue;
                        }
                    } else {
                        $value = array_merge($value, $buckets[$key]);
                    }
                }
            }
        } else {
            $key = $this->getModelKey($primaryModel, $link);
            $value = isset($buckets[$key]) ? $buckets[$key] : ($this->multiple ? [] : null);
        }
        if ($primaryModel instanceof ActiveRecordInterface) {
            $primaryModel->populateRelation($name, $value);
        } else {
            $primaryModels[$i][$name] = $value;
        }
    }
    if ($this->inverseOf !== null) {
        $this->populateInverseRelation($primaryModels, $models, $name, $this->inverseOf);
    }
    return $models;
}

            
via() 公共方法

指定与连接表关联的关系。请调用 via() 设置此属性,而不是直接设置它。此属性仅在关系上下文中使用。

yii\db\ActiveRecord 类中声明关系时使用此方法来指定枢纽记录/表

class Order extends ActiveRecord
{
   public function getOrderItems() {
       return $this->hasMany(OrderItem::class, ['order_id' => 'id']);
   }

   public function getItems() {
       return $this->hasMany(Item::class, ['id' => 'item_id'])
                   ->via('orderItems');
   }
}
public $this via ( $relationName, callable $callable null )
$relationName string

关系名称。这指的是 $primaryModel 中声明的关系。

$callable callable|null

一个 PHP 回调,用于自定义与连接表关联的关系。它的签名应该是 function($query),其中 $query 是要自定义的查询。

返回 $this

关系对象本身。

                public function via($relationName, callable $callable = null)
{
    $relation = $this->primaryModel->getRelation($relationName);
    $callableUsed = $callable !== null;
    $this->via = [$relationName, $relation, $callableUsed];
    if ($callable !== null) {
        call_user_func($callable, $relation);
    }
    return $this;
}