我有表格: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 param不会是我想要测试的唯一一个,可能有10个或更多。
基本上,我必须做所有这些,因为我无法通过yii2 joinWith()
方法发送任何参数。我不知道将WHERE
添加到由joinWith()
的急切加载生成的查询的最佳方法是什么。我以某种方式使它工作,但我认为这很脏。
有没有人想要更好/更清洁地解决这个问题?
答案 0 :(得分: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]);
}
答案 1 :(得分: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']
]);
}