Question

My Category Model:

class Category extends AppModel {
    public $displayField = 'name';

//    public $actsAs = array('Containable');

    public $hasAndBelongsToMany = array(
        'Post' => array(
            'className' => 'Post',
            'joinTable' => 'categories_postss',
            'foreignKey' => 'category_id',
            'associationForeignKey' => 'post_id',
            'unique' => 'keepExisting'
        )
    );
}

$params['contain'] = array('Post' => array(
            'limit'=> 3));
        pr($this->Category->find('first',$params)); exit;

It is fetching all Posts, irrespective of limit. What I want to do:

I have this page where I ma listing all the categories and latest 5 posts related to it. I want to limit the associated model to only 5 rows.

Any ideas?

Was it helpful?

Solution

Containable behavior is not in use

The most likely reason for this problem is that the containable behavior is not being used at all.

Compare, for the below code example:

$results = $this->Category->find('first', array(
    'contain' => array(
        'Post' => array(
            'limit' => 3
        )   
    )   
));

Without containable behavior, it'll generate the following queries:

SELECT ... FROM `crud`.`categories` AS `Category` WHERE 1 = 1 LIMIT
SELECT ... FROM `crud`.`posts` AS `Post` 
    JOIN `crud`.`categories_posts` AS `CategoriesPost` ON (...)

With containable behavior, it'll generate the following queries:

SELECT ... FROM `crud`.`categories` AS `Category` WHERE 1 = 1 LIMIT
SELECT ... FROM `crud`.`posts` AS `Post` 
    JOIN `crud`.`categories_posts` AS `CategoriesPost` ON (...) LIMIT 3

Given this (and the code in the question) check that the AppModel has the containable behavior in $actsAs:

<?php
// app/Model/AppModel.php
class AppModel extends Model {
    public $actsAs = array('Containable');
}

Limit always required?

Alternatively, or possibly in addition, you may prefer to put a limit in the association definition - To do so just define the 'limit' key:

class Category extends AppModel {

    public $hasAndBelongsToMany = array(
        'Post' => array(
            'limit' => 100, // default to a high but usable number of results
        )
    );
}

OTHER TIPS

the hasAndBelongsToMany relationship seems unnecessary to me. I think you only need Category hasMany Post and Post belongsTo Category relationships. Add category_id to the posts table. Make both models actAs containable.

Post Model

class Post extends AppModel {
     public $actsAs = array('Containable');

    var $belongsTo = array(
        'Category' => array(
            'className' => 'Category',
            'foreignKey' => 'category_id'
        ),
        // ... more relationships
    );

Category Model

class Category extends AppModel {
     public $actsAs = array('Containable');

    var $hasMany = array(
        'Post' => array(
            'className' => 'Post',
            'foreignKey' => 'category_id'
        ),
        // ... more relationships
    );

Categories Controller

class CategoriesController extends AppController {

    public $paginate = array(
        'Category' => array(
            'contain' => array(
                 'Post' => array(
                     'limit' => 3
                 ), // end Post
             ) // end Category contain
         ) // end Category pagination
     ); // end pagination

     public function index() {

         // for paginated results
         $this->set('categories', $this->paginate());

         // for find results
         $this->Category->contain(array(
             'Post' => array(
                 'limit' => 3
             )
         ));

     $this->set('categories', $this->Category->find('all'));

     } 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top