Tags

, , ,

Here’s an example of using the Containble behavior when you’ve got deep and complex model relationships.

Let’s consider the following model associations…

User->Profile
User->Account->AccountSummary
User->Post->PostAttachment->PostAttachmentHistory->HistoryNotes
User->Post->Tag

It’s very possible that each of those models has other associations, so we need to use Containable to retrieve just the models we need (we’ll also specify fields and conditions for some models just to make it more “fun”). Remember, that Containable behavior has to be attached to all of the models in our relationship, therefore to make your life easier you should probably attach the behavior to all models in App Model…

Our find() call:

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

Crazy, huh?

Some things to keep in mind:

  • ‘contain’ key is only used once in the main model, you don’t use ‘contain’ again for related models
  • Deep binding is done by using the ‘contain’=>array(‘ModelA’=>array(‘ModelB’=>array(‘ModelC’…
  • Each model can have it’s own set of find() options, by using ‘contain’=>array(‘ModelA’=>array(‘fields’=>…, ‘conditions’=> …, ‘ModelB’=>array(‘fields’=>…etc.
  • As rafaelbandeira3 pointed out, ‘fields’ and ‘conditions’ are the only keys that will be of use. ‘limit’, ‘recursive’, ‘group’ and ‘order’ will not produce desired results for any of the “contained” models.
  • Of course you can still apply them to the main model (i.e. User). Well, except ‘recursive’, which is not needed since Containable handles the associations for you