0 追蹤者

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
$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

屬性詳細資訊

隱藏繼承的屬性

$inverseOf 公共屬性

作為此關聯反向關聯的名稱。 例如,一個訂單有一個客戶,這意味著 “customer” 關聯的反向關聯是 “orders”,而 “orders” 關聯的反向關聯是 “customer”。 如果設定了此屬性,則將通過指定的關聯引用主記錄。 例如,$customer->orders[0]->customer$customer 將是相同的物件,並且訪問訂單的客戶端將不會觸發新的資料庫查詢。 此屬性僅在關聯上下文中使用。

另請參閱 inverseOf()

public 字串 $inverseOf null
$modelClass public property
$multiple public property

此查詢是否代表與多個記錄的關聯。此屬性僅在關聯環境中使用。如果為 true,此關聯將使用 all() 將所有查詢結果填充到 AR 實例中。如果為 false,則只會使用 one() 檢索結果的第一列。

public boolean $multiple null
$primaryModel public property

關聯查詢的主模型。這僅在具有動態查詢選項的延遲加載中使用。

$via public property

與連接表相關聯的查詢。請呼叫 via() 來設定此屬性,而不是直接設定它。此屬性僅在關聯環境中使用。

另請參閱 via()

public array|object $via null

方法詳情

隱藏繼承的方法

__clone() public method

複製內部物件。

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() public method

請參閱 yii\db\ActiveQueryInterface::all() 以取得更多資訊。

public yii\db\ActiveRecordInterface[] all ( $db )
$db
回傳 yii\db\ActiveRecordInterface[]
findFor() public method

尋找指定主記錄的相關記錄。

當以延遲方式存取 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();
}

            
inverseOf() public method

設定作為此關聯反向關聯的名稱。

例如,一個顧客有訂單,這表示 "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;
}

            
one() public method

請參閱 yii\db\ActiveQueryInterface::one() 以取得更多資訊。

public yii\db\ActiveRecordInterface|array|null one ( $db )
$db
回傳 yii\db\ActiveRecordInterface|array|null
populateRelation() public method

尋找相關記錄並將其填充到主模型中。

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;
}

            
via() public method

指定與連接表相關聯的關聯。

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 回呼函數。其簽章應為 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;
}