zen of coding

Use Set::merge() to modify the $paginate property

Let’s say you have a Posts controller, where you’ll need to paginate some posts in various actions.
You might have some “generic settings” as the manual recommends in your $paginate variable similar to this:

var $paginate = array('Post'=>array('limit'=>10, 'order'=>array('Post.modified DESC')));

Now, the above setting is probably going to work well for all of your actions where pagination is required. However, in some actions you need to also add a ‘contain’ key and maybe some ‘conditions’…

We can easily merge our main “setting” and any other desired keys we’d normally pass to $paginate, by using Set::merge()

Let’s say this is our extendedView() action of the Posts controller:

$this->paginate = Set::merge($this->paginate,
array('Post'=>array(
     'conditions'=>array(
        'Post.forum_id'=>$this->Session->read('Forum.id')),
     'contain'=>array('Thread'=>array('Professor', 'Student'))
)));
  • Hi, could you explain the difference between Set::merge and the plain php function array_merge ? Thanks and keep up the good work.

  • teknoid

    @Kalt

    This is from the Set::merge() description:

    “This function can be thought of as a hybrid between PHP’s array_merge and array_merge_recursive. The difference to the two is that if an array key contains another array then the function behaves recursive (unlike array_merge) but does not do if for keys containing strings (unlike array_merge_recursive). See the unit test for more information.

    Note: This function will work with an unlimited amount of arguments and typecasts non-array parameters into arrays.”

    Specifically here (I’m almost positive), array_merge() will not allow you to combine arrays with the ‘Post’ key because it won’t look at the array contents recursively and will just override the first ‘Post’ key with contents of another (i.e. the one defined in the action).

  • rafaelbandeira3

    Just a note, there’s no why to use a “Post” index in your PostsController::$paginate. You could use it without model’s name reference, as the only thing it will paginate are posts. Your code would be cleaner and more readable.

    And specifically in this case array_merge_recursive would do the trick, maybe presenting a case that you override ‘order’/’limit’ with strings/numerical params would be better.

  • teknoid

    @rafaelbandeira3

    Sure, unless you have an additional model that you need to paginate. In that case this approach makes more sense, but otherwise you’re right. Thanks for pointing it out.

%d bloggers like this: