Creating Reusable Elements with requestAction

By gwoo (gwoo)
This is a brief tutorial on using requestAction to produce reusable elements. Code samples for 1.1 and 1.2 are provided.
Creating reusable elements with requestAction is very simple. At the end, we can even cache the element using the new feature in 1.2.

Start of with a simple controller.

Controller Class:

Download code <?php 
class PostsController extends AppController {
    var 
$name 'Posts';

    function 
index() {
        
$posts $this->Post->findAll();
        if(isset(
$this->params['requested'])) {
             return 
$posts;
        }
        
$this->set('posts'$posts);
    }
}
?>

So, we created the Posts controller and we gave it an index action. Then we found all the posts, then if requestAction is used it will return the posts, otherwise it will set the posts for the view.

Now we can create a reusable element that will use requestAction. We create a file in /app/elements/posts.thtml, then add the code below.

View Template:

Download code
$posts = $this->requestAction('posts/index');
foreach($posts as $post):
    echo $post['Post']['title'];
endforeach;


Now we have the element we can include it in the layout, another element or a view template.

View Template:

Download code
<?php echo $this->renderElement('posts');?>


The code above is for 1.1. If you want to get into the goodness of Cake 1.2 you can look at the updated code below.

Controller Class:

Download code <?php 
class PostsController extends AppController {
    var 
$name 'Posts';

    function 
index() {
        
$posts $this->paginate();
        if(isset(
$this->params['requested'])) {
             return 
$posts;
        }
        
$this->set('posts'$posts);
    }
}
?>

Notice we changed the index action to use paginate instead.
In the view we can use paginate params to control what is returned.

View Template:

Download code
$posts = $this->requestAction('posts/index/sort:created/direction:desc/limit:10');
foreach($posts as $post):
    echo $post['Post']['title'];
endforeach;

Now we are only grabbing the latest 10 posts. Whoa, we just created a latest posts element without having to change our index action or create another action.

Lets call this one latest posts and cache it for an hour.
create the file /app/elements/latest_posts.ctp.

View Template:

Download code
<?php echo $this->element('latest_posts', array('cache'=>'+1 hour');?>

We can still use this element in any other view file.

There are other ways to use requestAction, but if you are looking to create reusable elements for your site, then this is the way to go.



 

Comments 342

CakePHP Team Comments Author Comments
 

Comment

1 Awesome

Wow, this is great, so useful. I never realised requestAction() could be called from the view like that, although I guess I should have realised it, if not this way, then through the view->controller->requestionAction() path.

The stuff in 1.2 looks brilliant - but I'm still using 1.1x for all my projects because its the "stable" version. How unstable is 1.2? Would you recommend using it on large scale client websites? If not, do you know what the schedule is for a stable release of 1.2?

Is there any documentation currently available about the differences between 1.1 and 1.2? It seems there's quite a lot.

Finally, on that note, are there sufficient differences to warrant a new major version release? Cake2.0
Posted Apr 13, 2007 by Neil Crookes
 

Comment

2 My 1.2 and I.

The stuff in 1.2 looks brilliant - but I'm still using 1.1x for all my projects because its the "stable" version. How unstable is 1.2? Would you recommend using it on large scale client websites? If not, do you know what the schedule is for a stable release of 1.2?

Is there any documentation currently available about the differences between 1.1 and 1.2? It seems there's quite a lot.


I dived in and begun using the 1.2 branch a couple months back for two "large enough" commercial projects - a paid online magazine and a real estate portal.

While i have had the odd challenge thrown my way with some code behaving badly and at times a shortage of documentation for some of the cooler features of 1.2, a quick search through the user groups, the trac or just hitting good old google, has given me all the answers i could need without too much hassle!

So my two cents would be, go for it so long as your willing to put in a little extra effort - which in the end isnt really extra time as some of the magic 1.2 can do for you almost has me worried i shall no longer be needed in the world of webdev. (its doing it all for me)

and a parting note too - there has been a new release of the 1.2branch which im told has cured some of the most common ailments reported.
Posted Apr 16, 2007 by Paul Webster
 

Comment

3 Using a parameter in element

I like the new approach with the element() very much. I started implementing a very small contents_controller, just for displaying some content, which could be edited by the user.

I get the information from the controller, as shown above, but every page has a different parameter $page. Because this is static information most of the time, caching makes a lot of sense. So I have also included the 'cache' => '+1 hour' to cache the requests.

The problem is, that I only have one element, which is used for the different pages, because I use a $page var from the controller to request the different pages.

So I have extended the element() implementation in view.php a little bit like this:

if($expires) {
$plugin = null;
if(isset($params['plugin'])) {
$plugin = $params['plugin'];
}
// this is new <<<<<<<<<<<<<
$param = null;
if(isset($params['param'])) {
$param = '_'.$params['param'];
}
// param parameter to extend the cacheFile name
$cacheFile = 'element_' . $plugin .'_' . convertSlash($name).$param;

Maybe somebody has a better idea for this, but I don't wanted to create a different element for every content page, that I have to create. Now with the new parameter 'param' I could extend the call for element with a additional parameter and the elements are cached in different files in APP/tmp/cache/views

// the call for element with additional parameter
// 'param', which is my variable $page
echo $this->element('content', array('cache' => '+1 hour', 'param' => $page) );

looking forward to get some hints on this.
Posted May 8, 2007 by Siegfried Hirsch
 

Question

4 great

hi Gwoo,

for long, I was looking for something like this..however, in my website, users have a choice to sorting the latest post either by created date or modified date. How can I use the above reusable element to change the created,sort, and limit parameter based on user's choice.

Ritesh
Posted May 17, 2007 by Ritesh Agrawal
 

Comment

5 How now shall we live

That being said, y'all need to stop using requestAction. While I recognize and fully support the fact that there is an occasional need for it, more often than not, it is evidence of poor design, and you're doing something that could be done differently, or more likely better.
Posted Jun 9, 2007 by Nate
 

Comment

6 Examples

Could you explain why or, even better, give examples? ;-)

Greetings, Benni.
Posted Jun 26, 2007 by Benjamin Graf
 

Comment

7 Cross module activity

Willing to except that we're all "bad programmers" but hey:

what is the right way to access controllers / models across Cake? for instance, I'm doing a one-to-many update where "Model_A"' is related to "Model_B" by a foreign key in "Model_B". in the "Model_A_controller"'s "update" function, I'd like to either get an instance of a "Model B" object or pass control to "Model_B_controller" and let it do the work. What is the "good programmer" way to do so?
Posted Jul 16, 2007 by Dave Edelhart
 

Comment

8 Elements vs. mini views

My initial thought of requestAction was about embedding a view into another view. Literally.
Instead of just reusing a controller action and a view. You need to adapt the controller action to behave differently when it's 'requested' or just called in the normal way.

Would it be possible to just include a 'mini view' from another view? For example: When I want to show a selected contact above my contact list. It then makes sense to create some sort of mini view for the selected contact. You can create / test / debug it by pointing your browser to /contacts/smallview/454. Once it works, include it with:

$this->requestAction('/contacts/smallview/'. $id);

Directly from your view where you would like the mini view to appear. That's it, no more fiddling around with sending the data to an element / lopping through arrays, etc.
Posted Jul 30, 2007 by Brammeleman
 

Question

9 One problem

Hi, i did it, same as you explain. But my browser shows me an error:

"Safari can’t open the page.
Too many redirects occurred trying to open “http://localhost/cake/”. This might occur if you open a page that is redirected to open another page which then is redirected to open the original page."

Any idea? Thanks
Posted Aug 21, 2007 by Jose Jimenez
 

Question

10 Integration cakephp with wordpress and wikimedia

i want to integrate wordpress and wikimedia in my project base on cake framework, but no idea how to do it, is there anyone who did it before or have any idea on this
Posted Aug 23, 2007 by Anuj Chauhan
 

Question

11 view using many controllers

Hi, i'm new in cakePHP and I want to know what's the convention to make a view that uses more than 1 controller. I mean, i have a view that shows a list of messages and a list of events. Where should I put the view file? in wich folder? Should I use elements?

thanx
Posted Nov 11, 2007 by Tiago Piccinin
 

Question

12 Reusable Elements

How to translate this code in smarty?

View Template:

$posts = $this->requestAction('posts/index');
foreach($posts as $post):
echo $post['Post']['title'];
endforeach;

I don't know how to connect (smarty) view element with (cake) controller?
Posted Mar 9, 2008 by Zoran