2015-02-18 3 views
2

Прямо сейчас у меня есть:Yii2 добавить условие в последнем цепных отношений

$products = Product::findAll([1,2,3,4]); 
foreach ($products as $product){ 
    $text = $product->part->type->texts; 
} 

Это возвращает соответствующие записи из таблицы Texts.

Но мне нужно иметь только 1 запись, и для этого мне нужно иметь еще одно условие в последнем соединении type->texts, которое не определено в модели. Это динамическая переменная сеанса.

Есть ли способ сделать это?

ответ

9

Если вы хотите изменить последнее отношение запрос, чтобы иметь дополнительное условие и возвращать одну запись вместо многих, просто изменить последнее отношение вызов следующим образом:

$text = $product->part->type->getTexts()->andWhere(...)->one(); 

Прямой вызов метода отношение возвращает yii\db\ActiveQuery экземпляр, так что вы можете изменить условия, как вы хотите.

Если вы хотите использовать модифицированную связь в более чем одном месте, создать отдельный метод для этого:

/** 
* @return yii\db\ActiveQuery 
*/ 
public function getDynamicText() 
{ 
    // Insert link from texts relation similar as in hasMany() and additional condition in andWhere() 
    return $this->hasOne(...)->andWhere(...); 
} 

И затем использовать его:

$text = $product->part->type->dynamicText; 
2

В этом случае scopes бы удобное решение, особенно если вы собираетесь использовать сложные условия.

1. Начнем с создания модели, которая расширяет ActiveQuery с помощью метода, который будет использоваться, чтобы добавить условия к запросу, например: active = 1

namespace app\models; 

use yii\db\ActiveQuery; 

class TextQuery extends ActiveQuery 
{ 
    public function active($state = 1) 
    { 
     $this->andWhere(['active' => $state]); // or any other condition 
     return $this; 
    } 
} 

2. Override find() метод ваша Text модель:

public static function find() 
{ 
    return new \app\models\TextQuery(get_called_class()); 
} 

3. Добавить метод в Type модели, которая извлекает ваши реляционные данные через новоиспеченный объем:

public function getActiveText() 
{ 
    return $this->hasMany(Text::className(), ['type_id' => 'id'])->active(); 
} 

Наконец, использовать его следующий образ:

$text = $product->part->type->activeText; 

Документы довольно ясно по этому вопросу, проверьте ' em вне.

Смежные вопросы