Trait yii\db\ActiveRelationTrait
實作於 | yii\db\ActiveQuery |
---|---|
自版本起可用 | 2.0 |
原始碼 | https://github.com/yiisoft/yii2/blob/master/framework/db/ActiveRelationTrait.php |
ActiveRelationTrait 實作了 active record 關聯式查詢的通用方法和屬性。
公共屬性
屬性 | 類型 | 描述 | 定義於 |
---|---|---|---|
$inverseOf | 字串 | 作為此關聯反向關聯的名稱。 | yii\db\ActiveRelationTrait |
$link | 陣列 | 建立關聯的主表和外表之欄位。 | yii\db\ActiveRelationTrait |
$modelClass | yii\db\ActiveRecord | yii\db\ActiveRelationTrait | |
$multiple | 布林值 | 此查詢是否表示與多個記錄的關聯。 | yii\db\ActiveRelationTrait |
$primaryModel | yii\db\ActiveRecord | 關聯式查詢的主模型。 | yii\db\ActiveRelationTrait |
$via | 陣列|物件 | 與連接表相關聯的查詢。 | 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() | 指定與連接表相關聯的關聯。 | yii\db\ActiveRelationTrait |
屬性詳細資訊
作為此關聯反向關聯的名稱。 例如,一個訂單有一個客戶,這意味著 “customer” 關聯的反向關聯是 “orders”,而 “orders” 關聯的反向關聯是 “customer”。 如果設定了此屬性,則將通過指定的關聯引用主記錄。 例如,$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 | 字串 |
關聯名稱 |
$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();
}
設定作為此關聯反向關聯的名稱。
例如,一個顧客有訂單,這表示 "orders" 關聯的反向是 "customer"。如果設定此屬性,主要記錄將透過指定的關聯被參考。例如,$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 | 字串 |
作為此關聯反向關聯的名稱。 |
回傳 | $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 | 字串 |
關聯名稱 |
$primaryModels | 陣列 |
主要模型 |
回傳 | 陣列 |
相關的模型 |
---|---|---|
拋出 | 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;
}
指定與連接表相關聯的關聯。
在 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 | 字串 |
關聯名稱。這指的是在 $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;
}
註冊 或 登入 以發表評論。