我有3张桌子:
clients
,traders
和client_trader_relation
客户可以有很多交易者,而交易者可以有很多客户,所以这是一个带有“数据透视表”的多对多关系。该关系在客户端模型中定义如下:
$relations = array(
'traders' => array(self::MANY_MANY, 'traders', 'client_trader_relation(client_id, trader_id)'),
);
现在假设在CGridView中显示所有客户的列表时,一切都可以正常工作,但是我也希望能够由特定交易者搜索客户(因此,如果其中一位交易者的ID为10,则返回该交易者客户)。
我已经在模型的search()函数中做到了这一点:
public function search()
{
$criteria=new CDbCriteria;
$criteria->with = 'traders';
$criteria->together = true;
$criteria->compare('traders.id', $this->search_trader);
}
search_trader
是添加到模型和规则的附加变量,因此可以用于搜索。
在此过程中,它成功地返回了指定交易者的所有客户,结果不包含任何其他相关交易者,仅包含我要搜索的交易者。我可以理解这种行为,因为这就是生成的SQL的工作方式。
我很好奇,是否可以通过某种方式返回所有交易者而无需进行任何其他查询/功能?如果没有,那么做这种事情的正确方法是什么?到目前为止,我只能想到模型中的某些功能,例如getAllTraders()
,它将手动查询与当前客户端相关的所有traders
。可以,我可以使用此功能显示交易者列表,但会产生其他查询和其他代码。
答案 0 :(得分:0)
您可以使用此功能禁用紧急加载:
$this->with(['traders' => ['select' => false]]);
但这将为每一行创建单独的查询,因此在GridView
中有20个客户端,您将获得额外的20个查询。 AFAIK没有干净,简单的方法可以有效地做到这一点。最简单的解决方法是定义其他关系,该关系将用于使用急切的加载来获取未经过滤的交易者:
public function relations() {
return [
'traders' => [self::MANY_MANY, 'traders', 'client_trader_relation(client_id, trader_id)'],
'traders2' => [self::MANY_MANY, 'traders', 'client_trader_relation(client_id, trader_id)'],
];
}
然后定义with
设置以进行快速加载:
$this->with([
'traders' => ['select' => false],
'traders2',
]);
然后,您可以使用$client->traders2
获取交易者的完整列表。
您也可以在relations()
中临时定义此关系:
$this->getMetaData()->addRelation(
'traders2',
[self::MANY_MANY, 'traders', 'client_trader_relation(client_id, trader_id)']
);