0

我有桌子:documentdocument_contentOne文档可以有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 个或更多。

基本上,我必须做所有这些,因为我无法通过 yii2joinWith()方法发送任何参数。我不知道添加WHERE到通过急切加载joinWith(). 我以某种方式使它工作,但我认为这很脏。

有没有人有更好/更清洁的解决方案来解决这个问题?

4

2 回答 2

0

型号#文档

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]);
}
于 2016-04-07T10:09:07.837 回答
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 回答