Yii1 search() by many-many relation returns 只有一个相关模型
Yii1 search() by many-many relation returns only one related model
我有 3 个 table:
clients
、traders
和 client_trader_relation
客户可以有很多交易者,而交易者可以有很多客户,所以这是一个 "pivot" table 的多对多关系。该关系在客户端模型中定义如下:
$relations = array(
'traders' => array(self::MANY_MANY, 'traders', 'client_trader_relation(client_id, trader_id)'),
);
现在在比方说 CGridView 中显示所有客户的列表时一切正常,但我也希望能够通过特定交易者搜索客户(所以如果其中一个交易者是 id 10,那么return这个客户)。
我在模型的 search() 函数中这样做过:
public function search()
{
$criteria=new CDbCriteria;
$criteria->with = 'traders';
$criteria->together = true;
$criteria->compare('traders.id', $this->search_trader);
}
search_trader
是添加到模型和规则中的附加变量,因此可用于搜索。
虽然这有效,但它成功地 returns 指定交易者的所有客户,结果不包含任何其他相关交易者,只是我正在搜索的那个。我可以理解这种行为,因为这就是生成的 SQL 的工作方式。
我很好奇是否有任何方法可以 return 所有 交易者从此类搜索中进行搜索而无需进行任何额外的 queries/functions?如果不是,那么做这种事情的正确方法是什么?至于现在,我只能想到模型中的某些功能,例如 getAllTraders()
会手动查询与当前客户端相关的所有 traders
。那行得通,我可以使用此功能来显示交易者列表,但它会产生额外的查询和额外的代码。
您可以使用它来禁用预先加载:
$this->with(['traders' => ['select' => false]]);
但这将为每一行创建单独的查询,因此在 GridView
中有 20 个客户端,您将获得额外的 20 个查询。据我所知,没有干净简单的方法可以有效地做到这一点。最简单的解决方法是定义附加关系,该关系将用于使用预先加载获取未过滤的交易者:
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
获取交易者的完整列表。
您也可以定义此关系 ad-hoc 而不是 relations()
:
$this->getMetaData()->addRelation(
'traders2',
[self::MANY_MANY, 'traders', 'client_trader_relation(client_id, trader_id)']
);
我有 3 个 table:
clients
、traders
和 client_trader_relation
客户可以有很多交易者,而交易者可以有很多客户,所以这是一个 "pivot" table 的多对多关系。该关系在客户端模型中定义如下:
$relations = array(
'traders' => array(self::MANY_MANY, 'traders', 'client_trader_relation(client_id, trader_id)'),
);
现在在比方说 CGridView 中显示所有客户的列表时一切正常,但我也希望能够通过特定交易者搜索客户(所以如果其中一个交易者是 id 10,那么return这个客户)。
我在模型的 search() 函数中这样做过:
public function search()
{
$criteria=new CDbCriteria;
$criteria->with = 'traders';
$criteria->together = true;
$criteria->compare('traders.id', $this->search_trader);
}
search_trader
是添加到模型和规则中的附加变量,因此可用于搜索。
虽然这有效,但它成功地 returns 指定交易者的所有客户,结果不包含任何其他相关交易者,只是我正在搜索的那个。我可以理解这种行为,因为这就是生成的 SQL 的工作方式。
我很好奇是否有任何方法可以 return 所有 交易者从此类搜索中进行搜索而无需进行任何额外的 queries/functions?如果不是,那么做这种事情的正确方法是什么?至于现在,我只能想到模型中的某些功能,例如 getAllTraders()
会手动查询与当前客户端相关的所有 traders
。那行得通,我可以使用此功能来显示交易者列表,但它会产生额外的查询和额外的代码。
您可以使用它来禁用预先加载:
$this->with(['traders' => ['select' => false]]);
但这将为每一行创建单独的查询,因此在 GridView
中有 20 个客户端,您将获得额外的 20 个查询。据我所知,没有干净简单的方法可以有效地做到这一点。最简单的解决方法是定义附加关系,该关系将用于使用预先加载获取未过滤的交易者:
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
获取交易者的完整列表。
您也可以定义此关系 ad-hoc 而不是 relations()
:
$this->getMetaData()->addRelation(
'traders2',
[self::MANY_MANY, 'traders', 'client_trader_relation(client_id, trader_id)']
);