CakePHP Containable Behavior

Published: on 3/7/08 | Comments (7)

The last week or so, I have been taking a good look at the latest release of CakePHP.

CakePHP.1.2.0.7296 RC2 is a great release, so a big pat on the back to the entire development team, and keep up the good work.

One of my favourite features of the this release is the new Containable Behaviour which was introduced back in change set 6918 and is a mixture of two behavoirs, the original Containable behavior by Felix Geisendörfer and the Bindable behavior by Mariano Iglesias.

Basically the behavior allows find operations to define restrictions on what models to get based on the 'contain' parameter, including ability to override binding settings on the fly.

A real world example

Demogan.com is a site I created a few months ago to provide a service to anyone in the UK buying or selling a business, the idea came from my personal experience of selling a business in the UK last year before moving out here to the Canaries and a personal wish that there had been something like this out there at the time.

The first incarnation of the site went up in about 3 weeks and has already attracted a large membership and has a steady list of new businesses being added, and so I have begun a pretty major re-write from the ground up.

So instead of the obligatory Blog tutorial, I thought I'd show how to apply the Containable behavior to this real world example.

Each business for sale is held in a Listing model, and has amongst others, the following relationships:

  • belongsTo Category
  • belongsTo Location
  • belongsTo User
  • belongsTo Subscription
  • hasMany Image
  • hasMany AdditionalPage
  • hasMany Shortlist

Now, whilst this has been cut down from the actual site, you should see by now that a simple find('all') statement on the Listing Model is going to return a huge amount of data, not only from it's own model fields, but also from all the related models.

Using $this->Listing->recursive = -1 helps to get rid of all the sub queries but doesn't leave all the information we need to show a basic listings browser, so in the past it has been overly complicated to get just the information you require without resorting to either custom SQL queries, hash tables or any other number of little tricks, but the new Containable Behavior changes all that.

Containable Behavior

OK, to start with we'll conect up the containable behavior by the inserting the following line in our Listing Model

var $actsAs = array('Containable');

Incidentally with the lastest release there is now the ability to attach behavior on the fly so instead of inserting the above in the model, I could also do:

$this->Listing->Behaviors->attach('Containable');

With the Containable Behavior in place I can now do something like:

$this->paginate = array(
            'conditions'=>array(
                'Listing.active'
            ),
            'limit'=>10,
            'order'=>'Listing.created DESC',
            'fields'=>array('Listing.id','Listing.title','Listing.description','Listing.price'),
            'contain'=>array(
                'Location.name',
                'Category.name',
                'Tenure.name',
                'Subscription.expires',
                'Image'=>array(
                    'conditions'=>array('Image.is_default'=>1),
                    'fields'=>array('Image.id','Image.caption')
                )
            ),
        );
        $this->set('listings',$this->Paginate('Listing'));

Note the Contain array here, in it I can pass just the fields that I want and even another array filtered so that in this example I get just the image information I want for the image that has 'is_default' set to 1.

Of course I have only just started delving into what can be done with the Containable Behavior, for anyone looking to find out what can be done, take a look at the test cases within the new release as there are some great examples in there.

Once again, a huge slap on the back to the core CakePHP development team, 1.2 stable can't be far away now.


Comments

1: Frank said

Hi, thanks very much for this quick tutorial and example, just what I needed and it got straight to the point. Cheers!


2: Luka said

This is the best explaination I could find on the subject of behavior "Containable". I'm new in Cake so I was confused with this because I thought recursive attribute wa just enough. This example really explained the problem and solution. Thanks


3: Spoom said

This is great stuff, very succinct. Much appreciated.


4: Sagar Aliyas Jackie said

Thanks Thanks.....Wat a useful tutorial!!!!!


5: Frode Knutsen said

The Containable behaviour is not a very smart design at all. It runs a query for each of the tables defined in the contain-array instead of left or inner join them with the first query.

I found a post specifying my concern. Have a look at this post: http://www.endyourif.com/cakephp-containable-statement-pitfalls/


6: Shane McCallum said

Good observation Frode, I turned on debugging and checked my SQL log to confirm and indeed each contained model is queried independently. This makes it no better than using recursive=-1 and making each model query independently. Not super impressed.


7: GarykPatton said I have been looking looking around for this kind of information. Will you post some more in future? I'll be grateful if you will.

Have Your Say





Please enter the code



About Studio Canaria

Studio Canaria is the web site of freelance web developer, Peter Butler. Articles on this site relate to designing, developing and marketing modern web applications.

Recent Comments

Imitnessisell on CakePHP Auth Component - Users, Groups & Permissions Revisited
Do you guy's believe in Michael Jackson dead? I don't. His is a legend for me and I fan of...
GarykPatton on CakePHP Containable Behavior
I have been looking looking around for this kind of information. Will you post some more in...
KattyBlackyard on CakePHP Currency Conversion Component
Hi, gr8 post thanks for posting. Information is useful!
BeergeCargo on CakePHP Auth Component - Users, Groups & Permissions Revisited
Nice theme on your web? Are you gues on Twitter? I d like to follow you for updates and stuff!
Guglielmo on CakePHP Auth Component - Users, Groups & Permissions Revisited
This logic can be extended on a single object using id of object?? example of a permission:...