lxa*_*lxa 2 cakephp has-and-belongs-to-many paginate containable cakephp-1.3
我需要对Product属于特定Category(HABTM关联)的s 列表进行分页.
在我的Product模型中,我有
var $actsAs = array('Containable');
var $hasAndBelongsToMany = array(
'Category' => array(
'joinTable' => 'products_categories'
)
);
Run Code Online (Sandbox Code Playgroud)
并在 ProductsController
$this->paginate = array(
'limit' => 20,
'order' => array('Product.name' => 'ASC'),
'contain' => array(
'Category' => array(
'conditions' => array(
'Category.id' => 3
)
)
)
);
$this->set('products', $this->paginate());
Run Code Online (Sandbox Code Playgroud)
但是,生成的SQL看起来像这样:
SELECT COUNT(*) AS `count`
FROM `products` AS `Product`
WHERE 1 = 1;
SELECT `Product`.`*`
FROM `products` AS `Product`
WHERE 1 = 1
ORDER BY `Product`.`name` ASC
LIMIT 20;
SELECT `Category`.`*`, `ProductsCategory`.`category_id`, `ProductsCategory`.`product_id`
FROM `categories` AS `Category`
JOIN `products_categories` AS `ProductsCategory` ON (`ProductsCategory`.`product_id` IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20) AND `ProductsCategory`.`category_id` = `Category`.`id`)
WHERE `Category`.`id` = 3
Run Code Online (Sandbox Code Playgroud)
(即它选择20 Products然后查询它们Categories)
虽然我需要
SELECT COUNT(*) AS `count`
FROM `products` AS `Product`
JOIN `products_categories` AS `ProductsCategory` ON `ProductsCategory`.`product_id` = `Product`.`id`
JOIN `categories` AS `Category` ON `Category`.`id` = `ProductsCategory`.`category_id`
WHERE `Category`.`id` = 3;
SELECT `Product`.*, `Category`.*
FROM `products` AS `Product`
JOIN `products_categories` AS `ProductsCategory` ON `ProductsCategory`.`product_id` = `Product`.`id`
JOIN `categories` AS `Category` ON `Category`.`id` = `ProductsCategory`.`category_id`
WHERE `Category`.`id` = 3
ORDER BY `Product`.`name` ASC
LIMIT 20;
Run Code Online (Sandbox Code Playgroud)
(即选择前20 Products属于Category同id= 3)
注意:
没有可能的解决方案Containable(正如Dave建议的那样)使用连接.
这篇文章提供了一个非常方便的帮助器,$this->paginate['joins']可以通过HABTM关联构建分页.
注意:仍然在寻找Containable比使用假hasOne装订更优雅的解决方案.
最后我找到了一种方法来做我想做的事情,所以将其作为答案发布:
要强制JOIN(并且能够通过相关模型上的条件进行过滤)Containable- 你必须使用假hasOne联想.
在我的情况下,代码ProductsController应该是:
$this->Product->bindModel(array('hasOne' => array('ProductsCategory')), false);
$this->paginate = array(
'limit' => 20,
'order' => array('Product.name' => 'ASC'),
'conditions' => array(
'ProductsCategory.category_id' => $category
),
'contain' => 'ProductsCategory'
);
$this->set('products', $this->paginate());
Run Code Online (Sandbox Code Playgroud)
注意false作为第二个参数bindModel- 这使得绑定持久化.这是必要的,因为之前的paginate()问题会重置临时绑定.所以你可能想要手动之后.find('count')find('all')unbindModel
此外,如果您的条件在HABTM关联模型中包含多个ID,您可能希望添加'group' => 'Product.id'到您的$this->paginate[](如Aziz在其答案中所示)以消除重复条目(仅适用于MySQL).
更新:
然而,与连接方法(由Dave建议)相比,这种方法有一个严重的缺点:条件只能应用于中间模型的外键(category_id在我的情况下); 如果要在关联模型中的任何其他字段上使用条件 - 您可能必须将另一个bindModel('hasOne')绑定中间模型添加到HABTM关联模型.
| 归档时间: |
|
| 查看次数: |
6991 次 |
| 最近记录: |