CakePHP and Layout - secret of data passing through
CakePHP, Development, Frameworks, PHP October 10th, 2007
In my current project I need to deal with Layout more than adding some header, static menu and footer in it. I need to have dynamic menu loaded from the database plus additional blocks which will contain some data related to the main content. The similar case is YouTube.com, where in every movie you have related movies from the right depending from the tags related to the main movie. I think you get the idea.
Well, searching in the CakePHP Manual, CakePHP Google Group or Bakery doesn’t saticfy mu understanding how to solve the case. Apart from $anything_for_layout: Making HTML from the View available to the layout article I didnt find anything on this topic. And this one sounds like a hack rather than a complex solution.
Then I decided to investigate my self the situation and here is my solution:
Let’s go through complete example. Let’s imaggine that we have to load a dynamic menu from the database in all pages. Menu is in the database.
Ok, first step is to create a menu component:
//Get the menu from the database
class MenuComponent extends Object {
function fetchData(&$controller){
//Dynamically Loading the model of the menu, because it's not necessary to have it on every controller.
App::import('Model', 'Menu');
$this->Menu = new Menu();
return $this->Menu->findAll();
}
}
?>
The component just fetch all data from the Menu table and return it as array.
Once we have this component we need to include it in our application. If we want to be loaded for all controllers the best place is app_controller.php
So, what we add in the AppController class? The callback beforeRender is executed always after all Controller’s actions. This small trick allow us to put extra array in $this->data variable. For our example it’s called menu, but you should set name which wont be in a conflict with other variables /as example I could mention if there is interface for editing the Menu/, so I would suggest array node with name something like ‘MenuBlock’ or similar, but for this example it’s not needed. Let’s keep it simple.
We have the data from the database and it is associated properly to $this->data array. Let’s make the Helper:
class MenuHelper extends Helper {
function display() {
//This extracting only the name of the menu from the multidimentional array.
$content = Set::extract($this->data['Menu'], '{n}.Menu.name');
$ret = '<li>'.implode('</li><li>', $content).'</li>';
$ret = '<ul>'.$ret.'</il>'
return $ret;
}
}
?>
Basicaly what this helper do is to extract the name and create a simple unsorted list.
Now whats left is to add this in the layout. Layouts are in app/views/layouts directory. The default one is called default.ctp. If you dont have default one in that directory, you can get it from cake/libs/view/templates/layouts/default.ctp. Once you have it then just add the following code in it in the proper position.
That’s it, now this menu list will be populated in all pages.
***Update from 06-Feb-2008 ***
As Gabe Chaney correctly mentioned in the comments below I missed the part how to add the helper in the layout.
Well, it is very easy and following code just extend the previous one:
Hopefully this will clarify this article ![]()
Add to:


[...] CakePHP and Layout - secret of data passing through | Dev weblog databinding a component and displaying its output in the layout. (tags: cakephp component layout view) Posted by Richard@Home Filed in 15 [...]
I’m coming from Rails and was really missing the content_for method, I still do, but this is a great workaround, thanks for sharing.
Thanks! It really works.
There’s just one issue in the helper: the $ret variable is not $ret .= ”… but $ret = ”…
I think nice tutorial but unfortunalty it not working for its shows undefined variable ; i can’t figureout the exact problem anybody help me why this shows undefined varialbe how we can rectify this ,thanks in adavnce
@All - thanks for your comments!
DannyC - you are completely right, with .= it will take wrong string and it will become mess. I will fix in the article right now.
@vipin - I just want to warn you that the example is writen for CakePHP 1.2, and as DannyC said - it’s working, but there is no guarantee that it would work in v1.1
loadModel is deprecated. Please use App::import instead.
Another question, can you share abit on what does your database look like to use this code? Is it just menu table with id, name, and pages?
@conankun - true, loadModel() is deprecated, but the article was written before the deprecation, so I will leave as it is.
About db model this example is made with one table with 2 fields in it - id and name. This is because I simplify the example as much as possible.
Hi,
I keep getting a
Fatal error: Class ‘Menu’ not found in /var/www/cake/app/controllers/components/calendar.php on line 8
What is wrong, Version 1.2.0.6311 beta
@Stacey Kingwill - I think you need to have create a model named Menu. because as far I can see look like there is no such class. This article is just prove of concept and is not tend to be full working demo.
i’m having trouble implementing this. i think i’ve got everything set except i cannot get the line of code in the layout to work. i can’t figure out how i can have access to the helper within the layout. any help would be appreciated.
Apologize to all guys commented here. I miss the part which explain how to get instance of the helper in layout.
Just small clarification: Properly because of sequence of the class inheritance, but it’s not possible to load helper in the usual way in AppController class. The $helpers variable get overwritten from the default helpers which are Html and Form.
there are 2 approaches to sort this out:
1. You need to add desired helper in every controller /but this is time consuming and not convenient/
2. The approach which I just added in the post.
So, hopefully this issue finally get sorted.
To help those that find this article, but can’t quite get it working. It think that they deprecated the ‘App::…’ part. Replace these with loadModel(’NameofMenu’). And things will be good.
Valerie, you are totally wrong
it’s upside down - loadModel() is the deprecated one and the App::import is the new way to load different classes in the memory. In fact it was written with loadModel in the beginning, but I change this to meet new convention in cake.