Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/phally/lazy_model

Lazy model loading for CakePHP 1.2 & 1.3.
https://github.com/phally/lazy_model

Last synced: 17 days ago
JSON representation

Lazy model loading for CakePHP 1.2 & 1.3.

Awesome Lists containing this project

README

        

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:

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 for HABTM never works, because CakePHP needs to fill all sorts of
settings in the associations and it needs at least the join model for that. You can optimize
this though. It will be only half loaded when you set the 'with', 'associationForeignKey' and
'joinTable' keys in your HABTM association. In this case CakePHP will only load the join model.

See the test cases for details on how to set it up.

You will notice it will make a bit of a mess. So I suggest you only do this when you really
need to. It is probably not even worth it. Another way to speed up HABTM is to not use it at
all. You can split things up as hasMany and belongsTo associations. More on this can be found
in the book under heading "What to do when HABTM becomes complicated?".
(See: http://book.cakephp.org/view/1034/Saving-Related-Model-Data-HABTM)

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/)