Connaxis Creative Outsourcing - Stay Competitive - Outsource Web Design to Argentina

Home » Blog
Blog
lang_btn lang_btn

CakePHP: Modifying layout blocks from within view elements

Added by:18 February 2009 17:56

Usually a website layout consists of some main content block surrounded by common elements like a header, menu and submenu. CakePHP lets you handle these common widgets from the layout file (e.g. default.ctp) and use the view files for the "main content". In practice the controller passes all the necessary view data to both the layout and the views. But what if you have a common layout element "submenu" which should show local tasks (e.g. "edit", "new") depending on the main view and you don´t want to pass these submenu items through the controller? In this case you would need the view to "talk" to your layout and tell it "to display the submenu items edit, new and export whereever they belong".

The solution is simple and actually there is already an example included in the CakePHP framework for this: the "Javascript" helper. With the javascript helper you can include JS files into the HTML header from within your views. Now we can do the same for our submenu. First we create a new helper called "menu" in "views/helpers". The helper just needs one method for now: "addSubmenuLink" :

<?php
/** file app/views/helpers/menu.php */
class MenuHelper extends AppHelper {
  function addSubmenuLink($label, $url) {
    $view =& ClassRegistry::getObject('view');
    $view->addSubmenuLink($label, $url);
  }
}

Than we overwrite the default View class with our custom AppView and extend it to add a new variable to the layout: "submenu_links":

<?php
/** file app/views/app.php */
class AppView extends View {
  var $__submenu_links = array();
  function addSubmenuLink($label, $url) {
    $this->__submenu_links[] = array('label'=>$label, 'url'=>$url);
  }
  function renderLayout($content_for_layout, $layout = null) {
    $this->set('submenu_links', $this->__submenu_links);
    return parent::renderLayout($content_for_layout, $layout);
  }
}

In order to use this new "AppView" class for all our controllers/views we need to set the "view" variable to "App" in our AppController:

<?php
/** file app/controllers/app_controller.php */
class AppController extends Controller {
  var $view = 'App';
}

To render the submenu we add the following code at any place to our layout file (e.g. default.ctp):

<?php if ($submenu_links) { ?>
  <ul id="submenu">
  <?php foreach ($submenu_links as $link) {
    ?>
    <li><?php echo $html->link($link['label'], $link['url']);     ?></li>
    <?php
  }
  ?>
  </ul>
<?php } ?>

Finally you just need to load your "menu" helper (add "menu" to the "helpers" array in your Controller) and use the following code in your view files to add submenu links:

$menu->addSubmenuLink('Edit', '/my_controller/edit/'.$my_id);
$menu->addSubmenuLink('Export PDF', '/my_controller/export_pdf/'.$my_id);

That's it! Now any view (or view element) can add submenu items to your submenu block in the layout and the controller does not even need to know about that.

Further reading

A good article with a slightly different approach is $anything_for_layout: Making HTML from the View available to the layout in the CakePHP Bakery.

 
dude
Posts: 3
Comment
Re:
Reply #3 on : Sat November 28, 2009, 00:46:56
tat sucks man....
Yanosh
Posts: 3
Comment
say tnx
Reply #2 on : Wed June 10, 2009, 08:45:04
:D
alex
Posts: 3
Comment
Re:
Reply #1 on : Mon April 20, 2009, 18:11:19
(^^,)