Some CakePHP requestAction….action
I’ve spent the last few months writing a portfolio system for Columbia College using CakePHP. One of the requirements was a template system that would allow students to choose different templates for their personal sites. I thought it would be a nice feature for users to have a template preview page that allowed them to choose a template from a menu and see what the template would look like with their data.
Initially, I built two separate views. One for the displaying the actual live site, and one for displaying the preview of the site. The two views were nearly identical, aside from a small menu bar at the top of the preview page. I didn’t like the idea that the code was repeated, so I thought that an element might be the solution. However, the templating system required some setup in the controller before the view was actually rendered. This was a problem because the template preview page was not in the same controller as the view for the user’s public page. More repeated code.
I started looking into the requestAction method, but I couldn’t find a whole lot of information about it. Some of what I did find was pretty negative. The manual suggests that one of the uses of requestAction is to retrieve data from another controller. I’m not so sure about using it for that sort of thing. To me, it seems like common data retrieval functions should go in the model. But rendering one action inside of another seemed like the perfect use of requestAction.
To create a dynamic preview page, I created a view with the menu bar that I wanted to appear above the site when it was being previewed. Then, where I wanted the templated page to be rendered I used requestAction to call the action that displayed the public site:
$this->requestAction("/$site_url/$preview_path",
array('template_id' => $template_id));
URLs for the site are structured with the student name and the name of the action being called: /student_name/action_name. Using requestAction I can call those urls, which get handled by the public controller. One caveat is that a view called by requestAction will render without a layout. In this case, that was exactly what I wanted, because the preview page was providing the layout for view.
But how does controller choose which template to render? That’s where the second parameter to requestAction comes in. The preview controller sets a template id based on the template the student chooses from the preview menu. The public controller also uses a template id, but that template id is stored as part of the user’s profile. To get the public controller to use the template id from the preview controller, I needed to pass it on somehow. The second parameter to requestAction allows you to pass an array of extra parameters on to the controller being called. Those extra parameters show up under $this->params in the controller being called. On the preview page I pass on a parameter called template_id. In the public controller I check for that parameter and if it’s not present I default to the user’s selected template:
$template_id = isset($this->params['template_id']) ?
$this->params['template_id'] :
$this->user['Options']['template_id'];
Aside from the template id change, the public controller behaves like it normally would, allowing the user to see a templated preview of their site.
So far, I haven’t seen any other practical uses for requestAction that couldn’t be better addressed by other features of CakePHP, but I’m curious about what other reasons people can find to use it.
March 12th, 2008 at 1:05 pm
Hi Matthew,
I think your design is pretty smart. However, as a developer with negative view of the function ‘requestAction()’, I would like to use aother way to solve the preview issue. Since the page to be previewed will possibly be an actual page, you may just give out the link of the preview action as the same as the actual url and pass the template id. The template id could be passed through session, database, or any mutually accessible places. The layout (or template) could be set on the fly. In the action of the controller, you may check whether the template is set. If so, change the value of $this->layout; otherwise, the page will be rendered using the default layout.
BTW, the site you made is pretty nice.
Steve
March 12th, 2008 at 1:15 pm
Thanks for the feedback! That was actually my first big CakePHP project, so there are probably a lot of areas that could have been improved.
I guess my reasoning behind doing it that way was that, by using requestAction() to load in the page I wanted to view, I could easily wrap any public page in the system with an outer template that had additional functionality for previewing templates with a minimal amount of additional code on the public pages.
The way I’ve done it on other sites, using other frameworks, is closer to the way you suggested. Typically, I put the additional content in the actual template, and have a flag that I check to determine if the additional preview content should wrap the template. Because the requestAction() option was there, I decided to try it out. In the future, I may avoid using requestAction() because, in general, I don’t really like a lot of the issues that come up when using it.
February 6th, 2010 at 10:28 pm
We use it on Popup Chinese for caching. If you want to cache a page (or the elements on that page) but still have some dynamic content, the controller won’t be run so your dynamic content either has to be stored in the Session or processed using a requestAction.