I'd think using a view helper. Ideally one that accesses a model to do the actual logic, so the logic could be used in other places if required - without duplication.
Hi,
I all ready made one site with Zend Framework, but now i would like to upgrade it. Currently I have 'menu' (urls) pages, on which 'content's are linked. Each content has it controller and action selected + layout position. In my layout.phtml script I run loop which actions to run >
But I don't like concept, because actions are run in layout...Code:$this->action($item['module.action'], $item['module.controller'], null, array('content' => $item));
In layout I would like only the placeholders where the action outputs are printed.
How to accomplishe this ?
I'd think using a view helper. Ideally one that accesses a model to do the actual logic, so the logic could be used in other places if required - without duplication.
Brenton Alker
PHP Developer - Brisbane, Australia
blog.tekerson.com | twitter.com/tekerson | brenton.mp
But $this->action is allready a view helper.
This is what i don't wont. I don't wont to run other conttroler actions in layout/views.
I would like to run all controller actions before the output, and put in some kind of container, and print all output in layout like this >
Code:<div id="left"> <?= $this->layout()->left ?> </div> <div id="center"> <?= $this->layout()->center ?> </div> <div id="right"> <?= $this->layout()->right ?> </div>
You might be able to accomplish this by using a front controller plugin. You could render the menus into variables which you can then assign as properties of the layout, then retrieve them later and output them using a view partial. This way you could always have the code and html available to any layout that needs it.
The plugin:
[PHP]
class My_Plugin_RenderMenu extends Zend_Controller_Plugin_Abstract
{
public function routeStartup(Zend_Controller_Request_Abstract $request)
{
$menuArray = array(); // run your action helpers here to get the correct data
$layout = Zend_Layout::getMvcInstance();
$layout->menu = $menuArray;
}
}
[/PHP]
In your layout:
[PHP]
<div class="columnLeft">
<?=$this->partial('partials/menu.phtml', array('menu' => $this->placeholder('Zend_Layout')->menu)) ?>
</div>
[/PHP]
layouts/partials/menu.phtml:
[PHP]
<ul>
<?php foreach($this->menu as $item): ?>
<li><a href="<?=$item['link'] ?>"><?=$item['text'] ?></a></li> // your data goes here...
<?php endforeach; ?>
</ul>
[/PHP]
Finally - register your plugin with the front controller in your bootstrap file:
[PHP]
$frontController = Zend_Controller_Front::getInstance();
$frontController->registerPlugin(new My_Plugin_RenderMenu);
[/PHP]
This is a pretty simple example, I think you would have to add your own logic for putting multiple outputs in different columns and such. However once you get something like this working it's quite easy to share it among layouts and you could also cache the rendered html from here if you wanted to, to make it even faster.
[PHP]class My_Plugin_RenderMenu extends Zend_Controller_Plugin_Abstract
{
public function routeStartup(Zend_Controller_Request_Abstract $request)
{
// fetch data from db
$contents = array(
0 => array('controller' => 'content', 'action' => 'index', 'position' => 'center'),
1 => array('controller' => 'contact', 'action' => 'form', 'position' => 'right'),
2 => array('controller' => 'newsletter', 'action' => 'login', 'position' => 'right'),
...
);
foreach ($contents as $items) {
foreach ($items as $item) {
// i would like to accomplishe next
$layout()->$item['position'][] = output from controller action ??
// each conttroler is generater, and output is assigned to layout (with position).
}
}
}
}[/PHP]
Is this posible? Yes? How?
I know you can do this, not 100% sure how but I know you would use the viewRenderer helper. I think you would define a controller action, set it's template as a property, and set $this->_helper->viewRenderer->setNoRender(true); Then you just set it to render the data with the template on the postDispatch() hook and have your other normal controllers extend this.
Sorry for the lack of details...this sounds like a clever way to deal with assigning menus and stuff so at some point I will probably do more research into how to do this but at the moment I don't have time. You should start with checking out the docs for the viewRenderer helper and this tutorial: djsipe.com Archive - Using a Single Template with Zend Framework’s ViewRenderer
I still did not found the solution.
Some has answered to me on stackoverflow, but it isn't what I wanted.
Modular web site with zend framework, stack of actions - Stack Overflow
I just can't figure it out ;(
With the action stack you can send request parameters
so you could:
[PHP]
class My_Plugin_RenderMenu extends Zend_Controller_Plugin_Abstract
{
public function routeStartup(Zend_Controller_Request_Abstract $request)
{
// fetch data from db
$contents = array(
0 => array('controller' => 'content', 'action' => 'index', 'position' => 'center_1'),
1 => array('controller' => 'contact', 'action' => 'form', 'position' => 'right_1'),
2 => array('controller' => 'newsletter', 'action' => 'login', 'position' => 'right_2'),
...
);
foreach ($contents as $items) {
foreach ($items as $item) {
$this->_helper->actionStack($items['action'],
$items['controller'],
$items['module'],
array('position' => $items['position']));
}
}
}
}
[/PHP]
and in the modular actions themselves you can do:
[PHP]
public function someAction() {
// do something
$this->_helper->viewRenderer
->setResponseSegment($this->_request('position', 'default_position'));
}
[/PHP]
And finally in your layout you would have something loke this
[PHP]
<div id="sidebar_left">
<?php echo $this->layout()->left_1?>
</div>
<div id="content">
<?php echo $this->layout()->center_1?>
</div>
<div id="sidebar_right">
<?php echo $this->layout()->right_1?>
<?php echo $this->layout()->right_2?>
</div>
[/PHP]
Since they are placeholders you could create a plugin which would replace every placeholders in a specific layout with a dropdown for selecting wich module would render at which position. Or one wich adds dropdown fonctionality for each blocks so an admin could reorder the blocks for a specific layout or even per page basis.
Last edited by inkubux; 02-27-2009 at 01:23 PM.
1.) $this->_helper-> doesn't exists in the Zend_Controller_Plugin_Abstract.
2.) I would like to have automated action building, I don't want to call $this->_helper->viewRenderer->setResponseSegment( for every action.
3.) Position array would be nice, $right[] so I can in layout do a loop, or just one echo for print all actions, that were assigned to that position.
I hessitate to say this because I get the feeling I've missed something from your description, so let me break down what I think you want...
- Request
- Dispatch to controller/action
- Prepare modal data and "pre-fetch" the data from other controller/actions
- Render view
You also don't want to call from the view script to another controller.
So when the request comes in it is dispatched to a specific action (lets call this the primary controller-action) which determines both what content to display and its location. However, the content itself is provided by another controller-action (the secondary controller-actions).
But because you don't want to just code this into the view what you essentially have to do is build an array of objects (or even just a HTML string) and place them in the primary controller-action to be rendered. And here's where I think you're going wrong...
To me it sounds like you're trying to work against the MVC design pattern by replacing proper use of models with the data returned by another request-response cycle. What I mean is if your content is already represented by some type of model class (e.g. the Zend table classes, etc) then you should simply load them in to the primary controller-action and use some type of view helper to dynamically render them using a template/phtml-fragment.
This allows you to separate the primary controller from any changes to the structure of the secondary ones, making your appliation less fragile. It also allows you to maintain the separation between models and views.
However, if you want to do what I think you want to do, I suggest you look at the implementation of the Partial View Helper and Zend_View::_run() as they will show you how to implement a rendering context so that you can pass in a variable $this as you do when using the normal zend views.
HTH
SNR