Paginate from within a model in CakePHP

Dave picture Dave · Jun 28, 2011 · Viewed 11.6k times · Source

I have a function in my Event model called getEvents - you can pass limit, start and end dates, fields, event types, and event subtypes.

I read that paginate can accept all the parameters I'm using like joins, conditions, limit...etc just like a normal find can.

It returns data just fine when I don't try to paginate. But - I'd like to be able to pass it a paginate variable to tell it instead of doing this:

$this->recursive = -1;
$data = $this->find('all', $qOptions);

to do this:

$this->recursive = -1;
$data = $this->paginate($qOptions);

When I try that, though, it gives me lots of errors. I can specify the errors later if needed - for now, I guess I'm looking for - is this something that can be done? If so, how?

Is there another better way to do something like this? I spent enough time making this function do just what I want, and allowing all the options passed...etc - it just seems like a waste if I can't also use it for pagination. But - if it's not ideal, I'm ok hearing that too. Thanks in advance.

EDIT:

I'm reading other things online that say you shouldn't use paginate in your model, because it draws from URL variables, which defeats the MVC structure purpose. This makes sense, but does that mean I have to write the same joins/queries in both model and controller? And in every action that it's needed?

Answer

Dave picture Dave · Jul 5, 2011

The way I figured out how I can keep my complex find in my model without having to rewrite it a second time in the controller is by passing a $paginate boolean variable.

If $paginate is true, it returns just the options created, which can then be used in the controller's pagination. If it's false (meaning we don't want to paginate), it returns the actual event results. So far this seems to be working.

In my getEvents() function (this method is in the Events model)

    if($paginate) {
        return $qOpts; // Just return the options for the paginate in the controller to use
    } else {
        $data = $this->find('all', $qOpts); // Return the actual events
        return $data;
    }

Then, in my Events/Index (events controller, index action - where I know I want pagination):

$this->Event->recursive = -1; // (or set recursive = -1 in the appModel)
$opts['paginate'] = true;

$paginateOptions = $this->Event->getEvents($opts);

$this->paginate = $paginateOptions; // Set paginate options to just-returned options
$data = $this->paginate('Event'); // Get paginate results
$this->set('data', $data); // Set variable to hold paginated results in view