Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I minimize the 'contain' queries in CakePHP?

I have three models, Users, Comments and Pages.

Users has many Comments, and Comments belong to Pages.

All models use the containable behavior, and default to recursive -1.

If I call a find() query on Comments, with the contain request including the Page model's field, this correctly returns the results using a single query, automagically joining the Page table to the user.

If I call a similar query from the User model (containing Comment and Comment.Page), the result is a query to source the Comments, followed by a query per comment to source the relevant Page.

Is there a way to configure the models to maintain the JOIN optimisation? I assumed the belongsTo declaration on the related model (Comments) would follow through to the host model (Users).

UPDATE

I should clarify, my question used a simplified version of my actual case study. Although the minimal solution I require would include this initial Model hasMany Model belongsTo Model structure, I am also looking for the solution at one or more additional belongsTo Models down the chain (which, I though, would automagically use LEFT JOINs, as this would be feasible).

like image 339
Rhys Avatar asked Oct 24 '12 10:10

Rhys


People also ask

What is contain in CakePHP?

A new addition to the CakePHP 1.2 core is the ContainableBehavior . This model behavior allows you to filter and limit model find operations. Using Containable will help you cut down on needless wear and tear on your database, increasing the speed and overall performance of your application.

How can I get data from database in CakePHP?

To view records of database, we first need to get hold of a table using the TableRegistry class. We can fetch the instance out of registry using get() method. The get() method will take the name of the database table as argument. Now, this new instance is used to find records from database using find() method.

How can I print query in CakePHP 2?

Add below code in app_model. php file which is located at root/cake/libs/model. Add below line in your model where you want print query. $last_query = $ this ->ModelName->getLastQuery();


1 Answers

Hmm that's interesting. That's a sort of optimization that should be implemented in the core :)

At any rate, I think you could get the same results (perhaps formatted differently) by building the query a little differently:

$this->User->Comment->find('all', array(
  'conditions' => array(
    'Comment.user_id' => $userId
  ),
  'contain' => array(
    'User',
    'Page'
  )
));

By searching from the Comment model, it should use two left joins to join the data since they are both 1:1 relationships. Note: The results array may look a little different than from when you search from the User model.

like image 106
jeremyharris Avatar answered Oct 30 '22 11:10

jeremyharris