Как использовать WHERE в yii2 joinWith(), который выполняет активную загрузку

У меня есть таблицы: document и document_content. One документ может иметь many содержание.

Я использую метод joinWith() для получения данных из таблицы document_content вместе с document с использованием отношений модели.

Выполняемые запросы следующие:

SELECT document.* FROM document INNER JOIN document_content ON document.id = document_content.document_id WHERE (lang='1') ORDER BY id DESC LIMIT 10

SELECT * FROM document_content WHERE document_id IN (665566, 665034, 664961, 664918, 664910, 664898, 664896, 664893, 664882, 664880)

У меня проблема с этим вторым запросом. Я хочу, чтобы он включал это предложение WHERE из первого: WHERE (lang='1')

Итак, я хочу, чтобы yii сгенерировал этот запрос:

SELECT * FROM document_content WHERE (lang='1') AND document_id IN (665566, 665034, 664961, 664918, 664910, 664898, 664896, 664893, 664882, 664880)

Мне как-то удалось этого добиться, но у меня есть повторение кода, и мне это не нравится. Должен быть какой-то лучший способ сделать это. Это мой код, который работает, но я думаю, что это не так хорошо:

/**
 * Returns documents by params.
 * 
 * @param  array $params the query params.
 * @return ActiveDataProvider
 */
public function findDocuments($params)
{
    /** @var $query ActiveQuery */
    $query = Document::find();

    // store params to use in other class methods.
    self::$_params = $params;

    // build dynamic conditions for document table
    $this->buildDocumentQuery($query);

    // build dynamic conditions for document_content table
    $this->buildDocumentContentQuery($query);

    // add conditions that should always apply here
    $dataProvider = new ActiveDataProvider([
        'query' => $query,
        'sort'  => ['defaultOrder' => ['id' => SORT_DESC]],
        'pagination' => [
            'pageSize' => 10,
        ],
    ]);

    return $dataProvider;
}

/**
 * Relation with document_content table.
 * 
 * @return DocumentContent
 */
public function getDocumentContent()
{
    $query = $this->hasMany(DocumentContent::className(), ['document_id' => 'id']);

    if (isset(self::$_params['lang'])) {
        $query->andFilterWhere([
            'lang' => self::$_params['lang'],
        ]);
    }
}

/**
 * Method that is responsible for building query conditions for document_content table.
 * 
 * @param  object $query ActiveQuery instance.
 * @return ActiveQuery
 */
public function buildDocumentContentQuery($query)
{
    if (isset(self::$_params['lang'])) {
        $query->innerJoinWith('documentContent');
    }

    return $query;
}

Как видите, я проверяю params['lang'] в двух местах. В моем методе отношения и в методе buildDocumentContentQuery(). Поэтому я повторяю один и тот же код в двух местах, и параметр lang не будет единственным, который я хочу протестировать, их может быть 10 или больше.

По сути, мне пришлось сделать все это, потому что я не мог отправить какие-либо параметры через метод yii2 joinWith(). Я не знаю, как лучше всего добавить WHERE к запросу, сгенерированному при нетерпеливой загрузке joinWith(). Я как-то заставил это работать, но я думаю, что это грязно.

Есть ли у кого-нибудь идеи для лучшего/более чистого решения этой проблемы?


person offline    schedule 07.04.2016    source источник


Ответы (2)


Модель#Документ

public function getDocuments($params)
{
    /** @var $query ActiveQuery */
    $query = Document::find();
    $query->getDocumentContentsByLanguage($params['lang']);
}

public function getDocumentContentsByLanguage($lang = null)
{
    return $this->hasMany(DocumentContent::className(), ['document_id' => 'id'])->where('lang = :lang', [':lang'=>$lang]);
}
person Xiaosong Guo    schedule 07.04.2016

Попробуй это:

$query = $this
   ->hasMany(DocumentContent::className(), ['document_id' => 'id']);

if (isset(self::$_params['lang']) && self::$_params['lang']==1) {
    $query
       ->joinWith('document')
       ->andWhere([
           Document::tablename().'.lang' => self::$_params['lang']
       ]);
}
person Vladislav Filonov    schedule 07.04.2016