Two step view process
by Naneau
Most of you will be familiar with the problem that of every HTML page you generate, only a certain part changes from page to page. For instance, on this very website (which has been created using wordpress) only the posts differ from page to page. The head section is the same on every page, as is the sidebar.
In the comments for my posts on smarty as well as in #zftalk there is a recurring question about how to achieve this. There are basically two paths you can follow:
The first is to create views that include the different sections that stay the same using some kind of require. In smarty this would be done by the {include} tag. In Zend_View PHP syntax, it would be done with:
1 | <?php $this->render('someTemplate.phtml'); ?> |
This has the advantage of great control over what gets rendered where. It has a big disadvantage because there will be repetition. If you wanted to change the order in which things get included, you would have to change all your views. In general, repetition is bad.
The second approach is to do a “reverse include”. When writing controllers for your different pages, it makes sense to just render the bit that changes. You can then put the result into some kind of global template. This approach is called a “two step view“. If you just have a single repeating part, it’s incredibly easy to write a front controller plugin that gets the body out of the response object, render a global view, and put the result of that into the response.
There are a few schools of thought on this subject. While I believe in keeping things simple, sometimes a more complex approach is required. Sometimes not just a single part of the page changes, but multiple parts. Some applications have multiple global views, etcetera. Things will get out of hand quickly. Zend_Layout will address that, although I’ve been lead to believe that it will probably not make 1.0.
Update
It appears we will get a final way to do two-step-views/layouts in 1.1. Until then, I will redirect you to Spotsec’s site for a tutorial on [Xend/Zend]_view.
Comments
Just an observation. In smarty you can also emulate a 2 step view using capture blocks.
Example:
page.tpl file:
{capture name=’content’ assign=’content’}
this is my content
{/capture}
{include file=’base.tpl’ content=$content}
base.tpl file:
{include file=’header.tpl’}
{include file=’sometemplate.tpl’}
{$content}
{include file=’footer.tpl’}
If this is a good approach is up to you to decide. This works for me.
Let’s hope that zend_layout comes soon because i really need the ability to call other actions and render/use there output in the current.
I think that the default MVC implementation in ZF was writing to serve ONE Action from ONE URI and that’s why a complex view has no intuitive place for the moment.
However if we look to the response object (Zend_Controller_Response_Abstract), we can realize that this object supports in its definition many named “bodies” (setBody($content, $name = null)).
What happens really is that : in Zend_Controller_Dispatcher_Standard::dispatch() there is only one action that will be called and the hole content will be added to the response although at this phase all what we need to feed other actions in other modules/controlles is there.
A work-around for this beahaviour is to fire an event for further dispatching in different actions. This is can be added to a static singleton instance (Later_View_Calls for example) with two functions :
- The view function : evalLater($action, $controller, $module, $params, $varname) to request for a further dispatching and in the .phtml file we place %”$varname” (for example %header if $varname = “header”) that will be replaced later with its value as if the entire ($action, $controller, $module, $params) was rendred to $varname
- The Later_View_Calls static function getLaterCalls() => witch return an array of array ($action, $controller, $module, $params, $varname) for a loop in dispatch() function. All the %var encountred by rendering the principal action (in .phtml) will be replaced by buffering ($action, $controller, $module, $params)
This is may be an another two step view rendring mecanisme. The php Zend_View code (or the engine in a templating world) is first evaluated than we look to the second step variables (the percent preceeded ones).
Hi Naneau!
After a long tries I have the convinience that Zend_Controller eat huge amount of ressources so that we can not clone the front controller in order to simulate another url dispatching! I hope the guys that orchestrate the MVC implementation review all this package.
For those who want to do with this “weak” MVC implementation, I suggest to separarate completely the process from the controller engine. In the action functions, you can put one line of code to call your one business functions or a mega-function : business($module, $controller, $action, $params) that decouple your business from ZF. If you want to use a complexe view, just call your business function to retreive all the puzzel pieces. Reusability is an old lesson that can simplify the life
Because I am not convienced with ZF MVC, I am searching other frameworks with strong MVC flavour. konstrukt looks very promising because it is very light and resolves only the controller issue.
Its logic is very clever. if you have an url such as basesite/node1/node2/../noden, you have to write all the controller node and forward from node (i) to node (i+1). All the nodes (component controllers) can be easily created from the parent node. so if you have an url such as /articles/My-Book-Review
you have to write an Articles controller and forward the $name = “My-Book-Review” to the Articles_Show controller. The complex rendering is also solved because you can at any level wrap the result of the child controller. konstrukt.dk for the curious who read this line
@Amine
The Zend_Controller is not meant to be cloned, but “simulating” multiple url dispatches can simply be done with the _forward() method provided by the Action controllers. While look at the design of konstrukt, it looks very wasteful, if you wanted a url scheme of /blog/archive/2007/06/13 then… This style really limits you to a certain url scheme and seems very dirty on the developer side by forwarding from node to node. When this could easily be implemented in ZF and other frameworks with the use of a custom router or route. Checking out the framework, it does not look very scalable compare to ZF and it lacks in many areas.
@Naneau
it was just a rant
Feel free to delete this
@Amine, Actually on reading your first post I now understand that you underestimated the features of ZF’s design. It does not limit you to one action per request.
Hi,
in konstrukt you have rather to use /blog/archive-2007-06-13 if you want rather then /blog/archive/2007/06/13, until there is some thing in /blog/archive and /blog/archive/2007 and /blog/archive/2007/06 and not only a 404 error page ! The more intuitive way is to keep url naviguable and human readable and this is more better than passing arguments.
I agree that _forward, even it looks private, helps to switch between many actions. However, this is not far from the way done in konstrukt when one controller initialize other controllers.
If the front controller is the main responsible for routing url to the suitable actions and this must happen once and in a single point, why _forward breaks this pattern in order to resolve some wake feature? why not rooting all to index controller and manage all the logic by _forward??? _forward sounds a work around solution, but it is not clean at all.
I don’t know if there is a way to do this :
Both URL mysite/admin/user/list
and URL mysite/admin/setting/theme/mytheme/style/
must share common permission checks but also provide the same presentation (layout).
However, the URL mysite/member and mysite/inscription must have different layouts and share the presentation with the children “node”. The 3 levels url architecture (Module/Controller/Action) is not suffisent if we dont add hierarchical relation between them. The presentation should reflect this relation too.
Could you explain me how this is possible with ZF ?
If we are not allowed to criticize a free open source project how it will be improved?
Thanks
First of all, including authentication logic into your controllers is generally not a good idea. It’s better to get that out of a controller and check for it during dispatch.
It is possible in the framework to do what you’re describing. There are even several paths one might follow. The one that comes to my mind first is to have a preDispatch() method in the “admin” controller, in that method you could check for authentication.
You are of course allowed to criticize all you want. In fact, I would like to encourage you to find as many faults with the framework as you can! You may want to subscribe to the fw-general mailing list too. There are people on the list that may be able to answer your questions with more details than I can provide.
Hi Naneau,
/* including authentication logic into your controllers is generally not a good idea */
That’s OK but this is what you suggest too
/*The one that comes to my mind first to have a preDispatch() method in the “admin” controller, in that method you could check for authentication” */
Hi Naneau,
in http://amine.olympe-network.com/?p=11, I present the specification of a tool that can help doing complex views and take into account the context when rendering. This lib may enforce the separation of the presentation and the model by offring a single point of contact to the presentation responsible.
I am starting writing the code, but I want to check if this concept already exists before to avoid writing the same thing twice.
Salutations.
There are some implementations. There’s Ralph Schindler’s Zend_Layout ( http://svn.ralphschindler.com/repo/Xend/ ) and there’s a proposal by Pádraic Brady which is outlined in the wiki ( http://framework.zend.com/wiki/pages/viewpage.action?pageId=33071 ).
I must admit though, that there is no “final” way of doing this yet, and I think there should be. Any proposals are welcome. It’s good to have some options to choose from
Hi,
Now that Zend have released an update to Zend_Layout to allow implementation of the two-step view, can you tell me how to get it working with Smarty? I’m new to Zend and Smarty so have used your integration technique (works really well – thanks!) but now want to implement the two-step layout using the new Zend method.
Can you help?!
cheers,
rich
College majors….
List of college majors. List of college majors in medical field. Descriptions of college majors. College majors and careers. Best college for communication majors….