1
votes

I am calling a find on a model called Book which is associated with a model Page(book_id)

However Page is associated with a model called Asset(page_id). I would like to get the array with all three models

Book
    Page1
        Asset1
        Asset2
        Asset3
    Page2
        Asset1
        Asset2
        Asset3

The code I have at the moment only get me Book and Page

$options = array(
    'conditions' => array('Book.' . $this->Book->primaryKey => $id),
    'contain' => 'Page'
);
$books = $this->Book->find('first', $options);

Book hasMany Pages Page hasMany Assets

1

1 Answers

3
votes

You can contain deeper associations, like it says in the docs

Example from the docs

$this->User->find('all', array(
    'contain' => array(
        'Profile',
        'Account' => array(
            'AccountSummary'
        ),
        'Post' => array(
            'PostAttachment' => array(
                'fields' => array('id', 'name'),
                'PostAttachmentHistory' => array(
                    'HistoryNotes' => array(
                        'fields' => array('id', 'note')
                    )
                )
            ),
            'Tag' => array(
                'conditions' => array('Tag.name LIKE' => '%happy%')
            )
        )
    )
));

Same thing with your models...

$options = array(
    'conditions' => array('Book.' . $this->Book->primaryKey => $id),
    'contain' => array('Page' => array('Asset')))
);
$books = $this->Book->find('first', $options);

Should work if your associations are set correctly (and if all models implement containable behavior).

EDIT
(to address the confusion the OP had)

The nested contain options works for the model expanding the array. For example, if models are associated like this

Model-A -> Model-B -> Model-C & Model-D
        -> Model-E -> Model-C

you could get the entire array with data like

Model-A
  Model-B1
    Model-C1
    Model-C2
    Model-D2
  Model-B2
    Model-C (null)
    Model-D3
  Model-E1
    Model-C1
    Model-C3

using something like

$this->ModelA->find('all'), array(
       'contain' => array(
          'Model-B' => array('Model-C', 'Model-D'),
          'Model-E' => array('Model-C')
       )
);

Also, you can add options to the containable array, including the ones used for searching, like 'conditions' (though be careful with this, it means that if the model doesn't match the condition it will return a null array, it does not mean the the whole "Model-A" will not be in the returned data since one of the nested conditions was not fulfilled).