views:

1718

answers:

2

How to build modular web site with Zend framework. I have pages in db, every page is represented as url. Every page has 1toN contents. Every content has controller, action and position (+other now not important columns). So, one request is one page and multiple contents (multiple actions). How can I build all actions before the output? I would like to have layout design like example bellow, where contents are put in there containers (actions are run before layout print-out).

<div id="left">
   <?= $this->layout()->left_container ?>
</div>
<div id="center">
   <?= $this->layout()->center_container ?>
</div>
<div id="right">
   <?= $this->layout()->right_container ?>
</div>

Until now I called actions from layout view, but I do not like this approach:

foreach ($contents as $item) {
    echo $this->action($item['action'], $item['controller'], null, array('content' => $item));
}

Thanks.

p.s.

adepretis's code is similar to my, views of my actions are run inside layout, which means that when error occurres it is printed in layout where the action is called. Is there no whey that actions are build before layout output? Another bad thing is that in every action I must run ...->setResponseSegment, I would like this to be automated.

p.s. #2

I have found answer, it is listed bellow as answer. If there is a whey I can do this easier please write it down.

+1  A: 

You can use the ActionStack helper. For example:

class MyController_Action extends Zend_Controller_Action {
    function init() {
        /** you might not want to add to the stack if it's a XmlHttpRequest */
        if(!$this->getRequest()->isXmlHttpRequest()) {
            $this->_helper->actionStack('left', 'somecontroller', 'somemodule');
            $this->_helper->actionStack('center', 'somecontroller', 'somemodule');
            $this->_helper->actionStack('right', 'somecontroller', 'somemodule');
        }
}

class MyController extends MyController_Action {
    function indexAction() {
        // do something
    }
}

class SomecontrollerController extends MyController_Action {
    function leftAction() {
        // do something

        $this->_helper->viewRenderer->setResponseSegment('left_container');
    }

    function centerAction() {
        // do something

        $this->_helper->viewRenderer->setResponseSegment('center_container');
    }

    function rightAction() {
        // do something

        $this->_helper->viewRenderer->setResponseSegment('right_container');
    }
}

A request for /somemodule/my/index results in executing /somemodule/somecontroller/left. /somemodule/somecontroller/right, /somemodule/somecontroller/center which end up in the correspondig layout segments.

Your code is similar to my, views of my actions are run inside layout, which means that when error occurred it is printed in layout; is there no whey that actions are build before layout output?Another bad thing is that in every action I must run ...->setResponseSegment, I would like this automated
glavić
I don't exactly get what you mean by "is there no whey that actions are build before layout output" ... the layout output is rendered after all actions have been executed. And for the "automation": if your Controllers extend MyController_Action the init() method does exactly this for all actions.
By that I mean, If you make an error in the action, it will be printed in the layout where it is positioned; so I am assuming that actions are called when they are put in layout. Example: echo $variableDoesntExists; in one of the actions, will print notice in the design...
glavić
A: 

I found my answer on other forum. Here is the asnwer:

MyPlugin

class MyPlugin extends Zend_Controller_Plugin_Abstract
{

    public function routeStartup(Zend_Controller_Request_Abstract $request)
    {
     $action_stack = new Zend_Controller_Action_Helper_ActionStack();
     // here I will read actions from db and run it in loop, but for example few are staticly added bellow
     $action_stack->actionToStack('index', 'content', 'default', array('position' => 'left'));
     $action_stack->actionToStack('index', 'content', 'default', array('position' => 'center'));
     $action_stack->actionToStack('index', 'edo', 'default', array('position' => 'center'));
     $action_stack->actionToStack('left', 'edo', 'default', array('position' => 'left'));
     $action_stack->actionToStack('right', 'edo', 'default', array('position' => 'right'));
    }

}

BaseController, that every controller extends

class BaseController extends Zend_Controller_Action
{

    public function preDispatch()
    {
     $position = $this->_request->getParam('position', false);
     if ($position) {
      $this->_helper->viewRenderer->setResponseSegment($position);
     }
    }

}

Layout.phtml

<div>
    <h2><u>LEFT:</u></h2>
    <?=$this->layout()->left?>
</div>
<div>
    <h2><u>CENTER:</u></h2>
    <?=$this->layout()->center?>
</div>
<div>
    <h2><u>RIGHT:</u></h2>
    <?=$this->layout()->right?>
</div>

This is what I wanted, if anyone has a better solution please answer the question and I will accept his answer.

glavić