0 フォロワー

トレイト yii\db\ActiveRelationTrait

実装元yii\db\ActiveQuery
利用可能なバージョン2.0
ソースコード https://github.com/yiisoft/yii2/blob/master/framework/db/ActiveRelationTrait.php

ActiveRelationTraitは、アクティブレコードのリレーションクエリのための共通のメソッドとプロパティを実装します。

公開プロパティ

継承されたプロパティを非表示

プロパティ 説明 定義元
$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 public プロパティ

このリレーションの逆となるリレーションの名前。例えば、注文には顧客がいるということは、「customer」リレーションの逆が「orders」であり、「orders」リレーションの逆が「customer」であることを意味します。このプロパティが設定されている場合、指定されたリレーションを通じてプライマリレコードが参照されます。例えば、$customer->orders[0]->customer$customer は同じオブジェクトとなり、注文の顧客にアクセスしても新しいDBクエリはトリガーされません。このプロパティはリレーションコンテキストでのみ使用されます。

inverseOf()も参照してください。

public 文字列 $inverseOf null
$modelClass public プロパティ
$multiple public プロパティ

このクエリが複数のレコードとのリレーションを表すかどうか。このプロパティはリレーションコンテキストでのみ使用されます。 trueの場合、このリレーションはall()を使用してすべてのクエリ結果をARインスタンスに投入します。 falseの場合、結果の最初の行のみがone()を使用して取得されます。

public 真偽値 $multiple null
$primaryModel public プロパティ

リレーションクエリのプライマリモデル。これは動的なクエリオプションを使用した遅延読み込みでのみ使用されます。

$via public プロパティ

中間テーブルに関連付けられたクエリです。直接設定するのではなく、このプロパティを設定するにはvia()を呼び出してください。このプロパティはリレーショナルコンテキストでのみ使用されます。

こちらも参照してください:via()

public array|object $via null

メソッドの詳細

継承されたメソッドを非表示

__clone() public メソッド

内部オブジェクトを複製します。

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 メソッド

詳細については、yii\db\ActiveQueryInterface::all()を参照してください。

public yii\db\ActiveRecordInterface[] all ( $db )
$db
return yii\db\ActiveRecordInterface[]
findFor() public メソッド

指定されたプライマリレコードの関連レコードを検索します。

このメソッドは、ActiveRecordのリレーションに遅延アクセスしている場合に呼び出されます。

public mixed findFor ( $name, $model )
$name 文字列

リレーション名

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

プライマリモデル

return mixed

関連レコード

throws 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 メソッド

このリレーションの逆となるリレーションの名前を設定します。

例えば、顧客は注文を持っており、これは「注文」リレーションの逆が「顧客」であることを意味します。このプロパティが設定されている場合、プライマリレコードは指定されたリレーションを介して参照されます。例えば、$customer->orders[0]->customer$customerは同じオブジェクトになり、注文の顧客にアクセスしても新しいDBクエリは発生しません。

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

この場合、結果は注文がどのようにロードされたかによって異なります。顧客が複数の注文を持っていると仮定しましょう。1つの注文のみがロードされた場合

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

変数$customerOrdersには1つの注文のみが含まれます。注文がこのようにロードされた場合

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

変数$customerOrdersには、顧客のすべての注文が含まれます。

public $this inverseOf ( $relationName )
$relationName 文字列

このリレーションの逆となるリレーションの名前。

return $this

リレーションオブジェクト自体。

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

            
one() public メソッド

詳細については、yii\db\ActiveQueryInterface::one()を参照してください。

public yii\db\ActiveRecordInterface|array|null one ( $db )
$db
return yii\db\ActiveRecordInterface|array|null
populateRelation() public メソッド

関連レコードを検索し、プライマリモデルにそれらを投入します。

public array populateRelation ( $name, &$primaryModels )
$name 文字列

リレーション名

$primaryModels 配列

プライマリモデル

return 配列

関連モデル

throws 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 メソッド

結合テーブルに関連付けられたリレーションを指定します。

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はカスタマイズされるクエリです。

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