Search code examples
cakephphas-manybelongs-to

hasMany relationship with conditions


The subject may be a common question but I have a bit more deeper problem. I am a freshman in CakePhp and already googled the issue. Unfortunately I could not find my exact solution.

My database structure is below with two tables and I used cakePhp naming conventions:

- news (id, news_title, news_text, is_active, created, modified)

- news_images (id, news_id, image_src, is_default, created, modified)

Each news has many images. But one image is being selected as default to-be used as a thumbnail in homepage.

In news listing pages, I want to list all news with a thumbnail. Thumbnail means, news_images.is_default=true

So I have to make a hasMany relationship but filtering with is_default=true

If I simply fetched data after hasMany and belongsTo relationship without using any conditions, it's retrieving all images. And I could not succeeded bingModal or container while I am too new to cakePhp.

I would like to request your help. Thanks in advance.


Solution

  • There are two main ways to accomplish what you want.

    A: Find Contain With Conditions

    $data = $this->News->find('all', array(
        'contain' => array(
            'NewsImage' => array(
                'conditions' => array(
                    'is_default' => true
                )
            )
        )
    ));
    

    B: Add Second Association to News model with Conditions

    This is the better method if you're going to perform this find call in more than one place.

    In model News (news.php):

    public $hasMany = array(
        'Image' => array(
            'className' => 'Image',
            'foreignKey' => 'news_id',
            'dependent' => false,
        ),
        'NewsThumbnail' => array(
            'className' => 'NewsImage',
            'foreignKey' => 'news_id',
            'conditions' => array('is_default' => true),
            'dependent' => false,
        )
    );
    

    Now you can find news, containing NewsThumbnail, and the conditions will be automatically applied.

    $data = $this->News->find('all', array(
        'contain' => array(
            'NewsThumbnail'
        )
    ));
    

    Note: If you add further conditions in the contain here, they will override the conditions set up in the model association, so you'll have to include them again.