特质 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 |
$link | array | 建立关系的主表和外表的列。数组键必须是此关系表的列,数组值必须是主表中的对应列。不要为列名添加前缀或引号,因为 Yii 会自动执行此操作。此属性仅在关系上下文中使用。 | 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 |
属性详细信息
此关系的逆关系的名称。例如,一个订单有一个客户,这意味着“客户”关系的逆关系是“订单”,而“订单”关系的逆关系是“客户”。如果设置了此属性,则主记录将通过指定的关系进行引用。例如,$customer->orders[0]->customer
和 $customer
将是同一个对象,访问订单的客户不会触发新的数据库查询。此属性仅在关系上下文中使用。
另请参阅 inverseOf()。
建立关系的主表和外表的列。数组键必须是此关系表的列,数组值必须是主表中的对应列。不要为列名添加前缀或引号,因为 Yii 会自动执行此操作。此属性仅在关系上下文中使用。
方法详细信息
克隆内部对象。
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]];
}
}
有关更多信息,请参阅 yii\db\ActiveQueryInterface::all()。
public yii\db\ActiveRecordInterface[] all ( $db ) | ||
$db | ||
返回 | yii\db\ActiveRecordInterface[] |
---|
查找指定主记录的相关记录。
当延迟访问 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();
}
设置此关系的逆关系的名称。
例如,一个客户有订单,这意味着 "订单" 关系的逆关系是 "客户"。如果设置了此属性,主记录将通过指定的关系进行引用。例如,$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 |
此关系的逆关系的名称。例如,一个订单有一个客户,这意味着“客户”关系的逆关系是“订单”,而“订单”关系的逆关系是“客户”。如果设置了此属性,则主记录将通过指定的关系进行引用。例如, |
返回 | $this |
关系对象本身。 |
---|
public function inverseOf($relationName)
{
$this->inverseOf = $relationName;
return $this;
}
有关更多信息,请参阅 yii\db\ActiveQueryInterface::one()。
public yii\db\ActiveRecordInterface|array|null one ( $db ) | ||
$db | ||
返回 | yii\db\ActiveRecordInterface|array|null |
---|
查找相关记录并将其填充到主模型中。
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() 设置此属性,而不是直接设置它。此属性仅在关系上下文中使用。
在 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 回调,用于自定义与连接表关联的关系。它的签名应该是 |
返回 | $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;
}
注册 或 登录 以便评论。