An eager loading beahavior plugin for CakePHP 2.x which is highly compatible to the Containable behavior but generates better queries.
- CakePHP 2.x
- PHP 5.3+
See the How to Install Plugins in the CakePHP documentation for general help.
- Put the
EagerLoader
directory into your plugin directory or install the plugin with Composer from the directory where your composer.json file is located:
php composer.phar require chinpei215/cakephp-eager-loader
- Load the plugin in your app/Config/bootstrap.php file:
CakePlugin::load('EagerLoader');
- And enable the behavior in your models or in your app/Model/AppModel.php:
class Post extends AppModel {
public $actsAs = array('EagerLoader.EagerLoader');
}
$Comment->find('first', [
'contain' => [
'Article.User.Profile',
'User.Profile',
]
]);
EagerLoaderBehavior
has a high compatibility with ContainableBehavior
, but generates better queries.
In the above example, only 2 queries will be executed such as the following:
SELECT
Comment.id, ...
FROM
comments AS Comment
LEFT JOIN articles AS Article ON (Comment.article_id = Article.id)
LEFT JOIN users AS User ON (Article.user_id = User.id)
LEFT JOIN profiles AS Profile ON (User.id = Profile.user_id)
WHERE
1 = 1
SELECT
User.id, ...
FROM
users AS User
LEFT JOIN profiles AS Profile ON (User.id = Profile.user_id)
WHERE
User.id IN (1, 2, 3)
If using ContainableBehavior
, how many queries are executed? 10 or more?
EagerLoaderBehavior
returns almost same results as ContainableBehavior
, however you might encounter incompatibility problems between the 2 behaviors.
For example EagerLoaderBehavior::contain()
is not implemented yet.
Then disabling EagerLoaderBehavior
on the fly, you can use ContainableBehavior::contain()
instead:
$Comment->Behaviors->disable('EagerLoader');
$Comment->Behaviors->load('Containable');
$Comment->contain('Article');
$result = $Comment->find('first');
For your information, EagerLoaderBehavior
can be coexistent with ContainableBehavior
.
$actsAs = [
'EagerLoader.EagerLoader', // Requires higher priority than Containable
'Containable'
]
Using this way, you need not to call load('Containable')
in the above example.