CakePHP Models and requestAction
| Tweet |
This may be kind of a “no duh” for some Cake veterans, but it was new to me, so I’ll share…
When it comes to accessing a different Model from a given Controller I had always wondered which was the better practice – include the other Model in the $uses array or using $this->requestAction() to get data from the other Model’s Controller.
For example, let’s say in the classic blog example you are in the PostsController and need to access some data from the AuthorsController. (Probably a bad example because in this case they would probably be joined by an Association, but pretend for a minute that they are not.)
I had always gone with this method – let the AuthorsController handle the Author data:
<?php class PostsController extends AppController { var $name = 'Posts'; function someaction($pid = null) { $post = $this->Post->findById($pid); $authname = $this->requestAction('/authors/getname/' . $post['Post']['author_id']); } } ?>
And again, that’s a very simple example, you would obviously have an association here…
The alternative would be to add the Authors Model in the PostsController’s $uses array:
class PostsController extends AppController { var $name = 'Posts'; var $uses = array('Post','Author'); function someaction($pid = null) { $post = $this->Post->findById($pid); $author = $this->Author->findById($post['Post']['author_id']); } }
The requestAction() method is probably a cleaner choice for occasional use, but I had a project where an Object could have 20 different associations. What I wanted to do though was let the user choose which “modules” to use. So those 20 different assocations could vary – I didn’t want to hard code them in the Models.
So the user chooses their modules and they are stored in a table. That table is then read and I was executing a loop through each of them and doing a requestAction for each of them to get the data from their respective Controllers. But the page was taking 20+ seconds to load. Looking at Cake’s debug output I noticed that for each of those requestAction’s, Cake was completely rebuilding the session data! (I store sessions in the DB)
The point? If you need to access data from multiple Controllers and can’t/don’t want to set up the appropriate associations for all of them, add them to the $uses array and turn on Model caching.
The Cake documentation clearly states that requestAction can lead to poor performance, but I guess I needed to see it for myself.
1 Comment »
RSS feed for comments on this post. TrackBack URI
Leave a comment
Line and paragraph breaks automatic, e-mail address never displayed, HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">

I would say that requestAction is to process the controller’s action, or even to render the view.
In the book.cakephp.org was written this:
[quote]This function calls a controller’s action from any location and returns data from the action.
You can use requestAction() to retrieve a fully rendered view by passing ‘return’ in the options: requestAction($url, array(‘return’));
[/quote]
So I would say calling using $uses is the better way. Another way is to use App::import(‘Model’, ‘ModelName’) or is the model has relation with the current model to use it with $this->CurrentModel->OtherRelatedModel->find()
Hope that helps
Comment by Nik Chankov — October 17, 2009 @ 12:08 pm