Can I paginate a custom query without overriding the default pagination?
In my CakePHP (1.2) app, I have two actions that both use pagination - index and search.
In a previous question I le开发者_开发知识库arnt that, in order to apply a threshold score to search results, I need to use the HAVING
MySQL keyword. Since CakePHP does not support this natively, I need to drop down to a custom query in order to accomplish this.
All the guides I can find to custom query pagination involve overriding the paginate()
and paginateCount()
methods.
Since I still want to be able to paginate normally on the index however, I don't want to change the normal pagination behaviour in the model.
Is there any way I can (ahem) have my Cake and eat it too?
Actually if you CAN do it with find you CAN do it with paginate. You can take a look here
But to be more especific you can add the conditions/limit/fields/contain/order etc that you use in find to the paginate function.
I haven't use group in the paginate but it SHOULD work :D
In your case you will have something like this:
$this->paginate = array(
'fields' => array(
'Product.category_id',
'COUNT(Product.hotel_id) as total'
),
'group' => array(
'Product.category_id HAVING COUNT(Product.hotel_id) > 1')
)
);
$data = $this->paginate('Product');
Hope it works, post a comment of your result, if it doesn't work you will have to override it, because it is not accepting the group condition... though I think it will work since pagination is a find in the end.
EDIT:
You may try to do something like this:
Override the paginate() and paginateCount() but with a tweak, sneak a condition so you can tell if its a pagination with having or not. Something like this:
function paginate($conditions, $fields, $order, $limit, $page = 1, $recursive = null, $extra = array()){
//if no having conditions set return the parent paginate
if (empty($conditions['having'])
return parent::paginate($conditions, $fields, $order, $limit, $page, $recursive, $extra)
//if having conditions set return your override
//override code here
}
Then you do something similar in paginateCount(), that way you have a selective paginate. remember to do unset $conditions['having'] once it is not needed or remember to put it somewhere that doesn't affect your find ;)
Actually getting this to work was more of a headache than you might reasonably expect.
Although I basically followed the advice of api55 (thanks!) I also jumped a load of other hurdles:
It's not possible to do
parent::paginateCount()
. I overcame this by overriding it with a different (and apparently better) version in app_model.php.Because
paginateCount()
is just a wrapper forfind('count')
, it doesn't accept afields
parameter. This is tricky for me as I rely on this to squeeze in my derived column (score of a full-text search). I got over this by passing the value offields
twice topaginate
- once asfields
and once as "sneaky
". Cake puts any parameters it doesn't recognize into theextra
array.Tying this together, I had an override of
paginateCount()
in my model that looks to see whetherextra
has an key called "sneaky". If it does, it does afind('all')
and uses the contents ofsneaky
to populate fields.
It's days like today that I have to step back and remember all the good points about using a framework.
精彩评论