CakePHP Containable Behavior Example
Recently a client needed a long page with a lot of data. I found CakePHP's Containable Behavior to be a quick and effective way to perform complex queries efficiently. Containable makes queries efficient because you only join the tables you need and you only fetch the columns whose values you need.
Below is an example that is similar to my code. Say you have a requirement to put 10 blog posts on a page, complete with associated slideshows and comments. Maybe it is a crazy web page or maybe it is the result of an API call. Anyhow, imagine your blog posts have an author who has an avatar. Each post may have a slideshow with any number of images. Posts may have many of comments and we want the comment text as well as the comment authors' names, emails, and avatars.
// in /app/models/post.php class Post extends AppModel { public $recursive = -1; public $actsAs = array('Containable'); // ... } // in /app/controllers/posts_controller.php class PostsController extends AppController { public function index() { $this->paginate = array( 'contain' => array( // we want to get the post author 'User' => array( // we just need his name and email 'fields' => array('first_name','last_name','email') // we also want to get his avatar image 'UserAvatar' => array( // we just need a few things from the user_avatars // table 'fields' => array('url','width','height'), ), ), // each post could have a slideshow 'PostSlideshow' => array( // we just need the basics about the images 'fields'=>array('caption','url','width','height'), ), // we also want to get all comments for each post 'PostComment' => array( // we really only need the comment text and date 'fields' => array('comment_text','created'), // but we also want to get the name and email of each // commenter 'User' => array( 'fields' => array('first_name','last_name','email'), // and we also want to get the commenters' avatars 'UserAvatar' => array( 'fields' => array('url','width','height'), ), ), ), ), // we just need a few things about each post 'fields' => array('headline','body','created'), // only get posts that are published 'conditions' => array( 'Post.published' => true, ), // show most recent first 'order' => 'Post.created DESC', 'limit' => 10, ); $posts = $this->paginate('Post'); $this->set(compact('posts')); } }
CakePHP's containable behavior has been key to keep my app running quickly. CakePHP will run an efficient set of queries. In the example above, it will query the `users` table once with a query like `SELECT first_name, last_name, email FROM users WHERE id IN(1,2,3,4)`.
