Question

Like the example in cakephp manual, http://book.cakephp.org/view/1323/Containable#Containing-deeper-associations-1325, i need to fetch data from a model through a condition on its association model.

I have:

Model Language:

class Language extends AppModel {

    var $name = 'Language';
    var $actsAs = array('Containable');

        var $hasMany = array(
        'LanguageTranslation' => array(
            'className' => 'LanguageTranslation',
            'foreignKey' => 'language_id'
        )
    );

}

And the association, ModelTranslation

class LanguageTranslation extends AppModel {

    var $name = 'LanguageTranslation';

    var $belongsTo = array(
        'Language'
    );
}

when i do:

$language_array = $this->controller->Language->find('all', array(
            'contain' => "LanguageTranslation.id = 1" 
        ));

i receive all the languages, not only one (because id in LanguageTranslation is unique). The result need to be one!

SO, with

debug($language_array);

result is:

Array
(
    [0] => Array
        (
            [Language] => Array
                (
                    [id] => 1
                    [code] => it
                    [locale] => ita
                )

            [LanguageTranslation] => Array
                (
                    [0] => Array
                        (
                            [id] => 1
                            [language_id] => 1
                            [language] => italiano
                        )

                )

        )

    [1] => Array
        (
            [Language] => Array
                (
                    [id] => 2
                    [code] => en
                    [locale] => eng
                )

            [LanguageTranslation] => Array
                (
                )

        )

    [2] => Array
        (
            [Language] => Array
                (
                    [id] => 3
                    [code] => de
                    [locale] => ger
                )

            [LanguageTranslation] => Array
                (
                )

        )
)

Why i don't catch only the Language with id = 1?

Was it helpful?

Solution

The conditions in containable apply only to the models inside the containment. Because the main query doesn't have any conditions it fetches every row in the table. In general you don't use containable to restrict the main query but to limit the way the query goes through the containment tree (very handy when you need to go through 3-4 levels of recursiveness where the results can get quite bloated if not contained).

In this case in particular if you are trying to get the data of a certain Language/LanguageTranslation pair, you can just pull the data from the LanguageTranslation model.

$this->Language->LanguageTranslation->find( 
    'first',
    array( 
        'conditions' => array( 'LanguageTranslation.id' => 1 ),
        'recursive'  => 1
    )
);

OTHER TIPS

linkable behavior will do the trick.

You can download it on: https://github.com/rafaelbandeira3/linkable

MODEL

var $actsAs = array('Linkable');

CONTROLLER

$language_array = $this->Language->find('all', array(
    'link' => array('LanguageTranslation'),
    'conditions' => array("LanguageTranslation.id = 1")
));

In regards to Juhana's answer: (which initially calls find on the Language Model), You can supply conditions for the parent model which target child models.

Contain in a separate call.

<?php

$this->Language->contain(array(
    'LanguageTranslation'
));
$lang = $this->Language->find('first', array(
    'conditions' => array('LanguageTranslation.id' => 1)
));

?>

Contain in one call.

<?php

$lang = $this->Language->find('first', array(
    'conditions' => array('LanguageTranslation.id' => 1),
    'contain' => array('LanguageTranslation')
));

?>

If you need to apply conditions to the child models just add the conditions array to the child model's index in the contain call. For example:

<?php

$this->Language->contain(array(
    'LanguageTranslation' => array(
        'conditions' => array('<LanguageTranslationConditionHere>')
    )
));

?>

Hope this helps!

-Andrew

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