トレイト yii\db\ActiveRelationTrait
実装元 | yii\db\ActiveQuery |
---|---|
利用可能なバージョン | 2.0 |
ソースコード | https://github.com/yiisoft/yii2/blob/master/framework/db/ActiveRelationTrait.php |
ActiveRelationTraitは、アクティブレコードのリレーションクエリのための共通のメソッドとプロパティを実装します。
公開プロパティ
プロパティ | 型 | 説明 | 定義元 |
---|---|---|---|
$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
は同じオブジェクトとなり、注文の顧客にアクセスしても新しいDBクエリはトリガーされません。このプロパティはリレーションコンテキストでのみ使用されます。
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 | ||
return | yii\db\ActiveRecordInterface[] |
---|
指定されたプライマリレコードの関連レコードを検索します。
このメソッドは、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();
}
このリレーションの逆となるリレーションの名前を設定します。
例えば、顧客は注文を持っており、これは「注文」リレーションの逆が「顧客」であることを意味します。このプロパティが設定されている場合、プライマリレコードは指定されたリレーションを介して参照されます。例えば、$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;
}
詳細については、yii\db\ActiveQueryInterface::one()を参照してください。
public yii\db\ActiveRecordInterface|array|null one ( $db ) | ||
$db | ||
return | yii\db\ActiveRecordInterface|array|null |
---|
関連レコードを検索し、プライマリモデルにそれらを投入します。
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;
}
結合テーブルに関連付けられたリレーションを指定します。
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コールバック。その署名は |
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;
}
サインアップまたはログインしてコメントしてください。