CakePHP Pagination With A HABTM Relationship

There are usually lots of Has And Belongs To Many relationship questions on the CakePHP mailing list. Since I am stupid about this stuff, I sought out Nate Abele and bugged him via IM until he agreed to give me an example of how to do this. Thanks Nate!

PHP:
  1. class Tag extends AppModel {
  2.  
  3.     var $hasAndBelongsToMany = 'Post';
  4.    
  5.     function paginate($conditions = null, $fields = null, $order = null, $limit = null, $page = 1, $recursive = null) {
  6.         $tag = $conditions['tag'];
  7.         unset($conditions['tag']);
  8.  
  9.         $this->hasAndBelongsToMany['Post'] = am(
  10.             $this->hasAndBelongsToMany['Post'],
  11.             compact('conditions', 'fields', 'order', 'limit', 'page')
  12.         );
  13.         return $this->findByName($tag);
  14.     }
  15.  
  16.     function paginateCount($conditions = null) {
  17.         $tag = $conditions['tag'];
  18.         unset($conditions['tag']);
  19.         $tmp = $this->hasAndBelongsToMany['Post'];
  20.         $this->hasAndBelongsToMany['Post']['fields'] = array('id');
  21.         $tag = $this->findByName($tag);
  22.         $this->hasAndBelongsToMany['Post'] = $tmp;
  23.         return count($tag['Post']);
  24.     }
  25. }
  26.  
  27. ?>
  28.  
  29. <?
  30. // Controller code
  31.  
  32. $data = $this->paginate('Tag', array('tag' => $tag));
  33. // Where $tag = some tag name

Okay, that's great but WHY does it work? Normally, when you do pagination you have to pass it a bunch of different parameters so it knows what records you wish to include as part of the data set you want to paginate over. In this example, you've already established that Tag HABTM Post. In order for the pagination query to correctly pull out the Posts that are also associated with the Tag, you need to merge the parameters you passed in to your 'paginate' method so that the CakePHP data mapping functionality knows what associated records are to be included. Then run your $this->findByName(...) and you're all set.

Article Tags >> || ||

3 Responses to this post.

  1. Leroy's Gravatar

    Posted by Leroy on 11.12.07 at 10:27 pm

    Well, I am even stupider about this stuff being new to php. But this caught my attention as I am just learning about creating and using classes. However, I would appreciate if I could recieve explanation as to how this script works and why

  2. Tarique Sani's Gravatar

    Posted by Tarique Sani on 11.12.07 at 10:27 pm

    I am now a bit confused - if you are getting and paginating Posts then shouldn't this logic go into the Post Model. Also if I implement the above in Tags how do I get a paginated list of Tags (for now lets forget why I would want to do that)?

  3. Fali's Gravatar

    Posted by Fali on 11.12.07 at 10:27 pm

    Well, function paginate is implemented in controller, you should put the paginate function in TagController and change the reference to $this->hasAndBelongsToMany['Post']['fields'] with $this->Tag->hasAndBelongsToMany['Post']['fields'], try it!.

Respond to this post

Want to advertise on this blog? Send email to chartjes@littlehart.net
GTcars Canadian Car Audio TurboDodge Car For Sale Sign
Audi Forum Mustang Forum Dodge Intrepid Miata Turbo
GTscene Pontiac Bonneville


@TheKeyboard is Digg proof thanks to caching by WP Super Cache!