LazyModel plugin Used to build CakePHP model chains when then they are actually used. This COULD increase the speed of your application and decrease it's memory usage significantly. It will be done fully transparent and will take only a single line of code in your application. Facts: - 100% compatible with CakePHP 1.2 and 1.3 (all model core tests pass). - Works on PHP 5.2 and 5.3. - Only loads models when they are needed. - Works fine with Containable and OneQuery (and probably Linkable). Setup: 1. Clone the plugin to your APP/plugins directory (or as a git submodule in that folder). 2. Put the following code in APP/app_model.php: <?php App::import('Lib', 'LazyModel.LazyModel'); class AppModel extends LazyModel { } ?> 3. See the magic happen. Q&A: Q: I have this page and it isn't really faster, doesn't it work? A: It probably does, but the speed increase can vary a lot. The more models and associations you have and the less you use them, the higher the speed increase will be. If you use every model, they will be instantiated just like CakePHP itself would do. Therefor it is important to use Containable or any other behavior that limits the number of models that is used. Using 'recursive' isn't advised. Q: What were you thinking when you made a Model as a Lib? A: This is by design. When importing a Model using App::import() CakePHP will automagically load AppModel for you. This is fine when loading a normal model, but if you want to apply this model to AppModel it will be causing an endless loop. This Model essentially is designed to be applied on every model and therefore implemented as a Lib. (See: http://github.com/cakephp/cakephp/blob/1.3/cake/libs/configure.php#L1154) The libs folder was introduced in CakePHP 1.3, but it was already possible to use Libs in CakePHP 1.2. It all boils down to some Inflector magic which was implemented earlier. Q: My HABTM isn't completely lazy loaded, is this a bug? A: No, full lazy loading only works when you specify your own model using the 'with' key in the association. This is because when using an auto model as join model CakePHP will need the two other models to guess the name of the join model and they still would be instantiated. So if you want to speed that up, use a 'with' model or don't use HABTM at all. Q: ACL breaks on CakePHP 1.2, is this a bug? A: Yes, but not one of this plugin. It has to do with the PHP4 compatibility of CakePHP. The problem is fixed in CakePHP 1.3 though. So if you can, upgrade fast! If you can't, just copy the ACL behavior to your application, find the line of the problem (see the error) which says: $model->{$type} =& ClassRegistry::init($type); Change it to: if (PHP5) { $model->{$type} = ClassRegistry::init($type); } else { $model->{$type} =& ClassRegistry::init($type); } This will get rid of the error. Q: When I use Model::deleteAll() on a 'with' model with only two fields directly, where the 'with' model is the primary model of the Controller, CakePHP still wants to delete records using the 'id' field. It used to work before. What can I do? A: Because CakePHP creates the models all at once by default, the primary key is set to one of the foreign IDs through the association of the parent HABTM model. LazyModel prevents the loading of those models, so the primary key isn't set. I tried to fix this, but it is unfixable without loading the other models first. There is a simple way to make it work though. Set the primary key to the right field before calling Model::deleteAll() like this: $this->Model->primaryKey = 'foreign_id'; $this->Model->deleteAll(array('foreign_id' => $id, 'other_foreign_id' => $fid)); This doesn't mean you always need to set the primary key before calling Model::deleteAll(). It only needs to be done in this specific case. Q: Hey, the 'required' classes in my forms are gone! Can I fix this? A: Duuh! The FormHelper checks whether a Model is set in the ClassRegistry or not and if it is, it will check the validation rules if it needs to add the 'required' class somewhere. So the reason the classes are gone is because the Models aren't in the ClassRegistry anymore. Fixing this is quite easy. Just call the Models you use in your action like this: public function admin_add() { $this->Model->AssociatedModel; $this->Model->OtherAssociatedModel; // Some data checking and saving. } This will instantiate the Models and place them in the ClassRegistry. Of course this will make the action slightly slower and bigger, but (in my opinion) it will still beat loading the entire model chain. Q: What the hell?! My form had a checkbox/textarea/whatever for a specific datatype and with LazyModel it has become just another text input. Where did it go? A: This issue is related to the previous one and can be fixed the same way. You can also add 'type' => 'textarea' to the options of FormHelper::input() for example to fix it. Q: Was this your own idea? A: Not really, there are more tries at this, but I couldn't really make them work like I had in mind and so started my own little project using a slightly different approach. However, I used the other attempts by Matt Curry and José Lorenzo Rodríguez as inspiration. (See: http://github.com/mcurry/lazy_loader/) (See: http://github.com/lorenzo/lazy_loader/) (See: http://bin.cakephp.org/saved/39855/)