0

私はテーブルを持っています:documentdocument_content. Oneドキュメントにはmanyコンテンツを含めることができます。

モデル関係を使用して、テーブルjoinWith()からデータを取得するメソッドを使用しています。document_contentdocument

実行されるクエリは次のとおりです。

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)

この 2 番目のクエリには問題があります。最初の WHERE 句からこの 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']、2 か所でチェックしています。私の関係方法とbuildDocumentContentQuery()方法で。そのため、2 つの場所で同じコードを繰り返していますが、テストしたいのは lang param だけではなく、10 以上ある可能性があります。

基本的に、yii2joinWith()メソッドを介してパラメーターを送信できなかったため、これをすべて実行する必要がありました。WHEREの熱心な読み込みによって生成されたクエリに追加する最良の方法がわかりませんjoinWith()。何とか動かせたのですが、これは汚いと思います。

この問題に対するより良い/よりクリーンな解決策について誰か考えがありますか?

4

2 に答える 2

0

これを試して:

$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']
       ]);
}
于 2016-04-07T10:10:58.320 に答える