5

How do I implement a sidebar in Zend Framework? I know that I can use a placeholder or something similar in Zend_layout, but how do I automatically generate the code for the sidebar in my controllers without having to call a sidebar class within every controller? My setup is as follows

Application
- modules
  - blog
  - other modules

I only want the sidebar for my blog module.

I have found this http://www.zfforums.com/zend-framework-components-13/model-view-controller-mvc-21/how-layout-sidebar-etc-2677.html but I do not understand the last part "just inject your layout, register it with the front controller ..."

unkownt
  • 621
  • 2
  • 8
  • 18

3 Answers3

6

You could just have a action and view in one of your controllers which renders the sidebar.

from the layout for the blog module you just call:

<? echo $this->action('action','controller','module',array('optionalparams'=>1); ?>

on the position where you want to have it. So one call to one action.

Rufinus
  • 29,200
  • 6
  • 68
  • 84
  • This is very expensive, I believe. – blockhead Aug 10 '09 at 11:48
  • what you mean by expensive ? AFAIK is this the way to do it. The code mentioned in the zfforums link, breaks with the MVC pattern IMHO. – Rufinus Aug 10 '09 at 12:09
  • Thank you, I knew that it should be easy. I just need to figure out how I can have different layouts per module. For now I am having the same layout for every module. Blockhead: How do you mean expensive? Would it be less expensive if I call the action within my controller? My first Idea was to create a default controller that fixed the sidebar and then inherit from that controller in all my blog controllers. – unkownt Aug 10 '09 at 12:12
  • 1
    unfortunatly at the moment ZF doesnt support a layout per moudle out of the box. but as always its not to hard to implement it. see http://dustint.com/archives/28 for details. – Rufinus Aug 10 '09 at 12:15
  • http://www.rmauger.co.uk/2009/03/why-the-zend-framework-actionstack-is-evil/ - Action Stack and Zend_View_Helper_Action are evil - they kill faeries in #zftalk, and takes a lot of extra processor/memory to create a request object and then dispatch it. $this->partial() would be better to use. The Action view helper may be removed in ZF 2.0 because of some of these factors. http://framework.zend.com/issues/browse/ZF-5840 – gnarf Aug 11 '09 at 09:34
  • @gnarf: good point, i actualy never had had a performance problem with it. but good to know, thanks. – Rufinus Aug 11 '09 at 11:58
4

Rather than use the action stack and the action() view helper, you could render a "partial view script" that includes your sidebar elements.

# in your layout.phtml
<div id="sidebar">
    <?php echo $this->render('blog/_sidebar.phtml'); /*relative to your view scripts directory*/ ?>
</div>

# in blog/_sidebar.phtml
<div id="blog_categories">
    <?php foreach ($this->categories as $category): ?>
        <?php echo $category->name; ?>
    <?php endforeach; ?>
</div>

The render() view helper is used to render the content of another view script. It has the same scope as all your other view scripts, so if there are any variable assigned to the view, they will be available to your partial. So in the example above, the categories variable was set in the controller.

There is another view helper called the partial() view helper. This function is a little more expensive since it creates its own variable scope. In other words, none of your current view variables will be available. You will have a clean slate to work with, which means you must pass in any variables you need:

# in your layout.phtml
<div id="sidebar">
    <?php echo $this->partial('blog/_sidebar.phtml', array('categories2'=>$this->categories)); ?>
</div>

# in blog/_sidebar.phtml
<div id="blog_categories">
    <?php foreach ($this->categories2 as $category): ?>
        <?php echo $category->name; ?>
    <?php endforeach; ?>
</div>

I don't find myself using partial() very often since it is more expensive, and I rarely need to create a separate context.

As far as setting up the variables for use in the sidebar partial ($this->categories in this example), I have used a number of different methods depending on the particular problem. If it's specific to a controller action, I will write the code and assign it in the view script:

# controller
public function somethingAction()
{
    $this->view->categories = $this->_getCategoriesForThisParticularAction();
    // other controller code
}

If my code is more generic to all the actions of the controller, I will utilize the controller's preDispatch() function. If it's more generic to multiple controllers, I will put the code in the init() of my base controller (a controller the most of my controllers extend).

Sometimes I do not even put the code in my controller. If it's simple enough, I just stick the code in the partial. If it's a little more complex, I will move it to a view helper. This may break the MVC pattern, but I think it really depends on the particular case in order to determine the best placement.

Andrew
  • 227,796
  • 193
  • 515
  • 708
3

If you are using Zend_Layout, just add the sidebar with the Action viewhelper as Rufinus said.

in your layout script:

<div id="sidebar">
<?php echo $this->action('action', 'controller', 'module', array('optionalparams'=>1)); ?>
</div>
<div id="content">
<?php echo $this->layout()->content; ?>
</div>

This should meet the requirements posted in your question.

Karsten
  • 14,572
  • 5
  • 30
  • 35