> Since the 'movies' table doesn't contain the genre_id I want to filter > on, how can I do a find on movies on a certain genre. As far as I can > see, I can't. Not without writing manual queries. Or am I wrong here? > > Any suggestions? > > Thanks, Dax.
I've been tackling a similar scenario myself. Hope the following will help you. I'm using CakePHP 1.1, so I wasn't able to use the new paginator introduced in 1.2. Here is a linik to the wonderful Paginator component by Andy Dawson: http://bakery.cakephp.org/articles/view/pagination Examine the article, download the code and play with it - works like a charm. When you've got it working for regular Model::findAll() queries (no HABTM filtering) read on to see how I managed to adapt it to work with HABTM filterings. For the HABTM filtering I found these threads in the google groups EXTREMELY useful: http://groups.google.com/group/cake-php/browse_thread/thread/8cbf01f7a9acda57/9e84f7aacbf3cd85?lnk=gst&q=tag+conditions&rnum=4#9e84f7aacbf3cd85 http://groups.google.com/group/cake-php/browse_thread/thread/f23b1825050ad543/014092749592de70 Andy Dawson and Jon Bennett are giving detailed explanations backed with some example code blocks At first it may look like it's too complicated, but it's not once you manage to grasp it. I must admit just reading the articles wasn't enough, but Andy was more than helpful providing additional hints on IRC. Long story short - you can't use offset and paged filterings, because HABTM associated models are not pulled from DB with JOINs. Joins are used for hasOne and belongsTo associations only. The solutions is to bind an additional hasOne association using a dummy (fake) model for the join table. Note: implementing this wouldn't in any way prevent your application's code based on your HABTM associated models to function normally. You'd just bind the extra model on the fly for the current action. Here's some example code from my case: Note, that I didn't use bindModel() on the fly, because I couldn't find a way to make the binding persistent. The pagination component makes a cuple of sql queries to get the pages, etc. so the associations gets reset to the ones defined in the models after the first query. The API for Cake 1.2 has a second parameter for Model::bindModel(array(), $reset = true) which can be passed as FALSE to make the bindings persistent. However, the API for Cake 1.1 doesn't have such a parameter, so I've associated the fake modek in the Bookmark's model definition. ### Models # bookmark.php class Bookmark extends AppModel { var $name = 'Bookmark'; var $hasAndBelongsToMany = array('Tag' => array('className' => 'Tag', 'joinTable' => 'bookmarks_tags', 'foreignKey' => 'bookmark_id', 'associationForeignKey'=> 'tag_id', 'conditions' => '', 'order' => '', 'limit' => '', 'unique' => true, 'finderQuery' => '', 'deleteQuery' => '', ) ); // NOTE: the fake association var $hasOne = array( 'BookmarkTagAssoc' => array('className'=>'BookmarkTag') ); } # tag.php class Tag extends AppModel { var $name = 'Tag'; var $recursive = 2; var $hasAndBelongsToMany = array( 'Image' => array('className' => 'Image', 'joinTable' => 'images_tags', 'foreignKey' => 'tag_id', 'associationForeignKey'=> 'image_id', 'conditions' => '', 'order' => '', 'limit' => '', 'unique' => true, 'finderQuery' => '', 'deleteQuery' => '', ), 'Bookmark' => array('className' => 'Bookmark', 'joinTable' => 'bookmarks_tags', 'foreignKey' => 'tag_id', 'associationForeignKey'=> 'bookmark_id', 'conditions' => '', 'order' => '', 'limit' => '', 'unique' => true, 'finderQuery' => '', 'deleteQuery' => '', ), ); } # bookmark_tag.php (the fake model) class BookmarkTag extends AppModel { // doesn't need anything else var $name = 'BookmarkTag'; var $useTable = 'bookmarks_tags'; } ### Controllers # bookmarks_controller.php class BookmarksController extends AppController { var $name = 'Bookmarks'; var $components = array ('othAuth', 'Pagination', 'Tagging'); var $uses = array('Bookmark','Tag'); // the action I'm using to get the bookmarks tagged with $id function admin_tag($id) { $this->uses[] = 'BookmarkTag'; $constraint['BookmarkTagAssoc.tag_id'] = $id; list($order,$limit,$page) = $this->Pagination- >init($constraint, null, $this->pagerSettings); $tempBookmarks = $this->Bookmark->findAll($constraint, NULL, $order, $limit, $page); foreach($tempBookmarks as $key => $row) { $tempBookmarks[$key]['Bookmark']['tagString'] = $this- >Tagging->getString($row['Tag'], $id); } $this->set('bookmarks', $tempBookmarks); $this->set('currentTagId', $id); foreach($_all_tags = $this->Tag->findAll() as $tag) { if($id === $tag['Tag']['id']) { $this->set('tagName', $tag['Tag']['name']); break; } } $this->pageTitle = 'Bookmarks'; $this->layout = 'admin'; } } I know how frustrated I felt when I was digging into this matter, so hopefully this will get you going. I'm copy/pasting this from my working copy so it is working :-) Credits go to Andy, Jon and the rest of the guys who keep on answering questions and making learning Cake a pleasant experience. Regards, Nasko --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Cake PHP" group. To post to this group, send email to cake-php@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/cake-php?hl=en -~----------~----~----~----~------~----~------~--~---