Applying Limit on associated model Cakephp 2.3x HA

2019-08-13 19:53发布

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?

2条回答
放荡不羁爱自由
2楼-- · 2019-08-13 20:06

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
        )
    );
}
查看更多
Luminary・发光体
3楼-- · 2019-08-13 20:22

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'));

     } 
查看更多
登录 后发表回答