1 <?xml version="1.0" encoding="UTF-8"?>
3 <sect3 id="zend.controller.actionhelpers.viewrenderer">
4 <title>ViewRenderer</title>
6 <sect4 id="zend.controller.actionhelper.viewrenderer.introduction">
7 <title>Introduction</title>
10 The <emphasis>ViewRenderer</emphasis> helper is designed to satisfy the
17 Eliminate the need to instantiate view objects within
18 controllers; view objects will be automatically registered
25 Automatically set view script, helper, and filter paths
26 based on the current module, and automatically associate
27 the current module name as a class prefix for helper and
34 Create a globally available view object for all dispatched
35 controllers and actions.
41 Allow the developer to set default view rendering options
48 Add the ability to automatically render a view script with
55 Allow the developer to create her own specifications for
56 the view base path and for view script paths.
63 If you perform a <methodname>_forward()</methodname>,
64 <methodname>redirect()</methodname>, or
65 <methodname>render()</methodname> manually, autorendering will not occur, as
66 by performing any of these actions you are telling the
67 <emphasis>ViewRenderer</emphasis> that you are determining your own
74 The <emphasis>ViewRenderer</emphasis> is enabled by default. You may
75 disable it via the front controller <emphasis>noViewRenderer</emphasis>
76 param (<command>$front->setParam('noViewRenderer', true);</command>) or
77 removing the helper from the helper broker stack
78 (<methodname>Zend_Controller_Action_HelperBroker::removeHelper('viewRenderer')</methodname>).
82 If you wish to modify settings of the <emphasis>ViewRenderer</emphasis>
83 prior to dispatching the front controller, you may do so in one
90 Instantiate and register your own
91 <emphasis>ViewRenderer</emphasis> object and pass it to the
95 <programlisting language="php"><![CDATA[
96 $viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer();
97 $viewRenderer->setView($view)
98 ->setViewSuffix('php');
99 Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);
105 Initialize and/or retrieve a <emphasis>ViewRenderer</emphasis>
106 object on demand via the helper broker:
109 <programlisting language="php"><![CDATA[
111 Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
112 $viewRenderer->setView($view)
113 ->setViewSuffix('php');
120 <sect4 id="zend.controller.actionhelper.viewrenderer.api">
124 At its most basic usage, you simply instantiate the
125 <emphasis>ViewRenderer</emphasis> and pass it to the action helper broker.
126 The easiest way to instantiate it and register in one go is to use
127 the helper broker's <methodname>getStaticHelper()</methodname> method:
130 <programlisting language="php"><![CDATA[
131 Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
135 The first time an action controller is instantiated, it will trigger
136 the <emphasis>ViewRenderer</emphasis> to instantiate a view object. Each
137 time a controller is instantiated, the <emphasis>ViewRenderer</emphasis>'s
138 <methodname>init()</methodname> method is called, which will cause it to set the
139 view property of the action controller, and call
140 <methodname>addScriptPath()</methodname> with a path relative to the current
141 module; this will be called with a class prefix named after the
142 current module, effectively namespacing all helper and filter
143 classes you define for the module.
147 Each time <methodname>postDispatch()</methodname> is called, it will call
148 <methodname>render()</methodname> for the current action.
152 As an example, consider the following class:
155 <programlisting language="php"><![CDATA[
156 // A controller class, foo module:
157 class Foo_BarController extends Zend_Controller_Action
159 // Render bar/index.phtml by default; no action required
160 public function indexAction()
164 // Render bar/populate.phtml with variable 'foo' set to 'bar'.
165 // Since view object defined at preDispatch(), it's already available.
166 public function populateAction()
168 $this->view->foo = 'bar';
174 // in one of your view scripts:
175 $this->foo(); // call Foo_View_Helper_Foo::foo()
179 The <emphasis>ViewRenderer</emphasis> also defines a number of accessors to
180 allow setting and retrieving view options:
186 <methodname>setView($view)</methodname> allows you to set the view
187 object for the <emphasis>ViewRenderer</emphasis>. It gets set as
188 the public class property <varname>$view</varname>.
194 <methodname>setNeverRender($flag = true)</methodname> can be used to
195 disable or enable autorendering globally, i.e., for all
196 controllers. If set to <constant>TRUE</constant>,
197 <methodname>postDispatch()</methodname>
198 will not automatically call <methodname>render()</methodname> in the
199 current controller. <methodname>getNeverRender()</methodname> retrieves
206 <methodname>setNoRender($flag = true)</methodname> can be used to
207 disable or enable autorendering. If set to <constant>TRUE</constant>,
208 <methodname>postDispatch()</methodname> will not automatically call
209 <methodname>render()</methodname> in the current controller. This
210 setting is reset each time <methodname>preDispatch()</methodname> is
211 called (i.e., you need to set this flag for each controller
212 for which you don't want autorenderering to occur).
213 <methodname>getNoRender()</methodname> retrieves the current value.
219 <methodname>setNoController($flag = true)</methodname> can be used to
220 tell <methodname>render()</methodname> not to look for the action script
221 in a subdirectory named after the controller (which is the
222 default behaviour). <methodname>getNoController()</methodname> retrieves
229 <methodname>setNeverController($flag = true)</methodname> is analogous
230 to <methodname>setNoController()</methodname>, but works on a global
231 level -- i.e., it will not be reset for each dispatched
232 action. <methodname>getNeverController()</methodname> retrieves
239 <methodname>setScriptAction($name)</methodname> can be used to
240 specify the action script to render. <varname>$name</varname>
241 should be the name of the script minus the file suffix (and
242 without the controller subdirectory, unless
243 <emphasis>noController</emphasis> has been turned on). If not
244 specified, it looks for a view script named after the action
245 in the request object. <methodname>getScriptAction()</methodname>
246 retrieves the current value.
252 <methodname>setResponseSegment($name)</methodname> can be used to
253 specify which response object named segment to render into.
254 If not specified, it renders into the default segment.
255 <methodname>getResponseSegment()</methodname> retrieves the current
262 <methodname>initView($path, $prefix, $options)</methodname> may be called
263 to specify the base view path, class prefix for helper and
264 filter scripts, and <emphasis>ViewRenderer</emphasis> options. You
265 may pass any of the following flags:
266 <emphasis>neverRender</emphasis>, <emphasis>noRender</emphasis>,
267 <emphasis>noController</emphasis>, <emphasis>scriptAction</emphasis>, and
268 <emphasis>responseSegment</emphasis>.
274 <methodname>setRender($action = null, $name = null, $noController
275 = false)</methodname> allows you to set any of
276 <emphasis>scriptAction</emphasis>, <emphasis>responseSegment</emphasis>, and
277 <emphasis>noController</emphasis> in one pass. <methodname>direct()</methodname>
278 is an alias to this method, allowing you to call this method
279 easily from your controller:
282 <programlisting language="php"><![CDATA[
283 // Render 'foo' instead of current action script
284 $this->_helper->viewRenderer('foo');
286 // render form.phtml to the 'html' response segment, without using a
287 // controller view script subdirectory:
288 $this->_helper->viewRenderer('form', 'html', true);
293 <methodname>setRender()</methodname> and <methodname>direct()</methodname>
294 don't actually render the view script, but instead set hints
295 that <methodname>postDispatch()</methodname> and
296 <methodname>render()</methodname> will use to render the view.
303 The constructor allows you to optionally pass the view object and
304 <emphasis>ViewRenderer</emphasis> options; it accepts the same flags as
305 <methodname>initView()</methodname>:
308 <programlisting language="php"><![CDATA[
309 $view = new Zend_View(array('encoding' => 'UTF-8'));
310 $options = array('noController' => true, 'neverRender' => true);
312 new Zend_Controller_Action_Helper_ViewRenderer($view, $options);
316 There are several additional methods for customizing path
317 specifications used for determining the view base path to add to the
318 view object, and the view script path to use when autodetermining
319 the view script to render. These methods each take one or more of
320 the following placeholders:
326 <emphasis>:moduleDir</emphasis> refers to the current module's base
327 directory (by convention, the parent directory of the
328 module's controller directory).
334 <emphasis>:module</emphasis> refers to the current module name.
340 <emphasis>:controller</emphasis> refers to the current controller name.
346 <emphasis>:action</emphasis> refers to the current action name.
352 <emphasis>:suffix</emphasis> refers to the view script suffix (which
353 may be set via <methodname>setViewSuffix()</methodname>).
359 The methods for controlling path specifications are:
365 <methodname>setViewBasePathSpec($spec)</methodname> allows you to change
366 the path specification used to determine the base path to
367 add to the view object. The default specification is
368 <filename>:moduleDir/views</filename>. You may retrieve the current
369 specification at any time using
370 <methodname>getViewBasePathSpec()</methodname>.
376 <methodname>setViewScriptPathSpec($spec)</methodname> allows you to
377 change the path specification used to determine the path to
378 an individual view script (minus the base view script path).
379 The default specification is
380 <filename>:controller/:action.:suffix</filename>. You may retrieve
381 the current specification at any time using
382 <methodname>getViewScriptPathSpec()</methodname>.
388 <methodname>setViewScriptPathNoControllerSpec($spec)</methodname> allows
389 you to change the path specification used to determine the
390 path to an individual view script when
391 <emphasis>noController</emphasis> is in effect (minus the base view
392 script path). The default specification is
393 <filename>:action.:suffix</filename>. You may retrieve the current
394 specification at any time using
395 <methodname>getViewScriptPathNoControllerSpec()</methodname>.
401 For fine-grained control over path specifications, you may use
402 <link linkend="zend.filter.inflector">Zend_Filter_Inflector</link>.
403 Under the hood, the <emphasis>ViewRenderer</emphasis> uses an inflector to
404 perform path mappings already. To interact with the inflector --
405 either to set your own for use, or to modify the default inflector,
406 the following methods may be used:
412 <methodname>getInflector()</methodname> will retrieve the inflector. If
413 none exists yet in the <emphasis>ViewRenderer</emphasis>, it creates
414 one using the default rules.
418 By default, it uses static rule references for the suffix
419 and module directory, as well as a static target; this
420 allows various <emphasis>ViewRenderer</emphasis> properties the
421 ability to dynamically modify the inflector.
427 <methodname>setInflector($inflector, $reference)</methodname> allows you
428 to set a custom inflector for use with the
429 <emphasis>ViewRenderer</emphasis>. If <varname>$reference</varname> is
430 <constant>TRUE</constant>, it will set the suffix and module directory as static
431 references to <emphasis>ViewRenderer</emphasis> properties, as well
438 <title>Default Lookup Conventions</title>
441 The <emphasis>ViewRenderer</emphasis> does some path normalization to
442 make view script lookups easier. The default rules are as
449 <emphasis>:module</emphasis>: MixedCase and camelCasedWords are separated by
450 dashes, and the entire string cast to lowercase. E.g.:
451 "FooBarBaz" becomes "foo-bar-baz".
455 Internally, the inflector uses the filters
456 <classname>Zend_Filter_Word_CamelCaseToDash</classname> and
457 <classname>Zend_Filter_StringToLower</classname>.
463 <emphasis>:controller</emphasis>: MixedCase and camelCasedWords are
464 separated by dashes; underscores are converted to directory
465 separators, and the entire string cast to lower case.
466 Examples: "<classname>FooBar</classname>" becomes "foo-bar";
467 "<classname>FooBar_Admin</classname>" becomes
468 "<filename>foo-bar/admin</filename>".
472 Internally, the inflector uses the filters
473 <classname>Zend_Filter_Word_CamelCaseToDash</classname>,
474 <classname>Zend_Filter_Word_UnderscoreToSeparator</classname>, and
475 <classname>Zend_Filter_StringToLower</classname>.
481 <emphasis>:action</emphasis>: MixedCase and camelCasedWords are separated
482 by dashes; non-alphanumeric characters are translated to
483 dashes, and the entire string cast to lower case.
484 Examples: "fooBar" becomes "foo-bar"; "foo-barBaz"
485 becomes "foo-bar-baz".
489 Internally, the inflector uses the filters
490 <classname>Zend_Filter_Word_CamelCaseToDash</classname>,
491 <classname>Zend_Filter_PregReplace</classname>, and
492 <classname>Zend_Filter_StringToLower</classname>.
499 The final items in the <emphasis>ViewRenderer</emphasis> <acronym>API</acronym> are the
500 methods for actually determining view script paths and rendering views.
507 <methodname>renderScript($script, $name)</methodname> allows you to
508 render a script with a path you specify, optionally to a
509 named path segment. When using this method, the
510 <emphasis>ViewRenderer</emphasis> does no autodetermination of the
511 script name, but instead directly passes the
512 <varname>$script</varname> argument directly to the view object's
513 <methodname>render()</methodname> method.
518 Once the view has been rendered to the response object, it
519 sets the <emphasis>noRender</emphasis> to prevent accidentally
520 rendering the same view script multiple times.
527 <methodname>Zend_Controller_Action::renderScript()</methodname>
528 proxies to the <emphasis>ViewRenderer</emphasis>'s
529 <methodname>renderScript()</methodname> method.
536 <methodname>getViewScript($action, $vars)</methodname> creates the path
537 to a view script based on the action passed and/or any
538 variables passed in <varname>$vars</varname>. Keys for this array
539 may include any of the path specification keys ('moduleDir',
540 'module', 'controller', 'action', and 'suffix'). Any
541 variables passed will be used; otherwise, values based on
542 the current request will be utlized.
546 <methodname>getViewScript()</methodname> will use either the
547 <emphasis>viewScriptPathSpec</emphasis> or
548 <emphasis>viewScriptPathNoControllerSpec</emphasis> based on the
549 setting of the <emphasis>noController</emphasis> flag.
553 Word delimiters occurring in module, controller, or action names will be
554 replaced with dashes ('-'). Thus, if you have the controller name
555 '<command>foo.bar</command>' and the action '<command>baz:bat</command>', using
556 the default path specification will result in a view script path of
557 '<filename>foo-bar/baz-bat.phtml</filename>'.
563 <methodname>Zend_Controller_Action::getViewScript()</methodname>
564 proxies to the <emphasis>ViewRenderer</emphasis>'s
565 <methodname>getViewScript()</methodname> method.
572 <methodname>render($action, $name, $noController)</methodname> checks
573 first to see if either <varname>$name</varname> or
574 <varname>$noController</varname> have been passed, and if so, sets
575 the appropriate flags (responseSegment and noController,
576 respectively) in the ViewRenderer. It then passes the
577 <varname>$action</varname> argument, if any, on to
578 <methodname>getViewScript()</methodname>. Finally, it passes the
579 calculated view script path to <methodname>renderScript()</methodname>.
584 Be aware of the side-effects of using <methodname>render()</methodname>: the
585 values you pass for the response segment name and for
586 the noController flag will persist in the object.
587 Additionally, noRender will be set after rendering is
595 <methodname>Zend_Controller_Action::render()</methodname> proxies to
596 the <emphasis>ViewRenderer</emphasis>'s <methodname>render()</methodname>
604 <methodname>renderBySpec($action, $vars, $name)</methodname> allows you
605 to pass path specification variables in order to determine
606 the view script path to create. It passes
607 <varname>$action</varname> and <varname>$vars</varname> to
608 <methodname>getScriptPath()</methodname>, and then passes the resulting
609 script path and <varname>$name</varname> on to
610 <methodname>renderScript()</methodname>.
616 <sect4 id="zend.controller.actionhelper.viewrenderer.basicusage">
617 <title>Basic Usage Examples</title>
619 <example id="zend.controller.actionhelper.viewrenderer.basicusage.example-1">
620 <title>Basic Usage</title>
623 At its most basic, you simply initialize and register the
624 <emphasis>ViewRenderer</emphasis> helper with the helper broker in your
625 bootstrap, and then set variables in your action methods.
628 <programlisting language="php"><![CDATA[
629 // In your bootstrap:
630 Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
634 // 'foo' module, 'bar' controller:
635 class Foo_BarController extends Zend_Controller_Action
637 // Render bar/index.phtml by default; no action required
638 public function indexAction()
642 // Render bar/populate.phtml with variable 'foo' set to 'bar'.
643 // Since view object defined at preDispatch(), it's already available.
644 public function populateAction()
646 $this->view->foo = 'bar';
649 // Renders nothing as it forwards to another action; the new action
650 // will perform any rendering
651 public function bazAction()
653 $this->_forward('index');
656 // Renders nothing as it redirects to another location
657 public function batAction()
659 $this->_redirect('/index');
666 <title>Naming Conventions: Word Delimiters in Controller and Action Names</title>
669 If your controller or action name is composed of several
670 words, the dispatcher requires that these are separated on
671 the <acronym>URL</acronym> by specific path and word delimiter characters. The
672 <emphasis>ViewRenderer</emphasis> replaces any path delimiter found
673 in the controller name with an actual path delimiter ('/'),
674 and any word delimiter found with a dash ('-') when creating
675 paths. Thus, a call to the action
676 <filename>/foo.bar/baz.bat</filename> would dispatch to
677 <methodname>FooBarController::bazBatAction()</methodname> in
678 <filename>FooBarController.php</filename>, which would render
679 <filename>foo-bar/baz-bat.phtml</filename>; a call to the action
680 <filename>/bar_baz/baz-bat</filename> would dispatch to
681 <methodname>Bar_BazController::bazBatAction()</methodname> in
682 <filename>Bar/BazController.php</filename> (note the path
683 separation) and render <filename>bar/baz/baz-bat.phtml</filename>.
687 Note that the in the second example, the module is still the
688 default module, but that, because of the existence of a path
689 separator, the controller receives the name
690 <classname>Bar_BazController</classname>, in
691 <filename>Bar/BazController.php</filename>. The ViewRenderer mimics
692 the controller directory hierarchy.
696 <example id="zend.controller.actionhelper.viewrenderer.basicusage.example-2">
697 <title>Disabling Autorender</title>
700 For some actions or controllers, you may want to turn off the
701 autorendering -- for instance, if you're wanting to emit a
702 different type of output (<acronym>XML</acronym>, <acronym>JSON</acronym>, etc),
703 or if you simply want
704 to emit nothing. You have two options: turn off all cases of
705 autorendering (<methodname>setNeverRender()</methodname>), or simply turn it
706 off for the current action (<methodname>setNoRender()</methodname>).
709 <programlisting language="php"><![CDATA[
710 // Baz controller class, bar module:
711 class Bar_BazController extends Zend_Controller_Action
713 public function fooAction()
715 // Don't auto render this action
716 $this->_helper->viewRenderer->setNoRender();
720 // Bat controller class, bar module:
721 class Bar_BatController extends Zend_Controller_Action
723 public function preDispatch()
725 // Never auto render this controller's actions
726 $this->_helper->viewRenderer->setNoRender();
734 In most cases, it makes no sense to turn off autorendering
735 globally (ala <methodname>setNeverRender()</methodname>), as the only thing
736 you then gain from <emphasis>ViewRenderer</emphasis> is the autosetup of
741 <example id="zend.controller.actionhelper.viewrenderer.basicusage.example-3">
742 <title>Choosing a Different View Script</title>
745 Some situations require that you render a different script than
746 one named after the action. For instance, if you have a
747 controller that has both add and edit actions, they may both
748 display the same 'form' view, albeit with different values set.
749 You can easily change the script name used with either
750 <methodname>setScriptAction()</methodname>, <methodname>setRender()</methodname>,
751 or calling the helper as a method, which will invoke
752 <methodname>setRender()</methodname>.
755 <programlisting language="php"><![CDATA[
756 // Bar controller class, foo module:
757 class Foo_BarController extends Zend_Controller_Action
759 public function addAction()
761 // Render 'bar/form.phtml' instead of 'bar/add.phtml'
762 $this->_helper->viewRenderer('form');
765 public function editAction()
767 // Render 'bar/form.phtml' instead of 'bar/edit.phtml'
768 $this->_helper->viewRenderer->setScriptAction('form');
771 public function processAction()
773 // do some validation...
775 // Render 'bar/form.phtml' instead of 'bar/process.phtml'
776 $this->_helper->viewRenderer->setRender('form');
780 // otherwise continue processing...
787 <example id="zend.controller.actionhelper.viewrenderer.basicusage.example-4">
788 <title>Modifying the Registered View</title>
791 What if you need to modify the view object -- for instance,
792 change the helper paths, or the encoding? You can do so either
793 by modifying the view object set in your controller, or by
794 grabbing the view object out of the <emphasis>ViewRenderer</emphasis>;
795 both are references to the same object.
798 <programlisting language="php"><![CDATA[
799 // Bar controller class, foo module:
800 class Foo_BarController extends Zend_Controller_Action
802 public function preDispatch()
804 // change view encoding
805 $this->view->setEncoding('UTF-8');
808 public function bazAction()
810 // Get view object and set escape callback to 'htmlspecialchars'
811 $view = $this->_helper->viewRenderer->view;
812 $view->setEscape('htmlspecialchars');
819 <sect4 id="zend.controller.actionhelper.viewrenderer.advancedusage">
820 <title>Advanced Usage Examples</title>
822 <example id="zend.controller.actionhelper.viewrenderer.advancedusage.example-1">
823 <title>Changing the Path Specifications</title>
826 In some circumstances, you may decide that the default path
827 specifications do not fit your site's needs. For instance, you
828 may want to have a single template tree to which you may then
829 give access to your designers (this is very typical when using
830 <ulink url="http://smarty.php.net/">Smarty</ulink>, for
831 instance). In such a case, you may want to hardcode the view
832 base path specification, and create an alternate specification
833 for the action view script paths themselves.
837 For purposes of this example, let's assume that the base path to
838 views should be '<filename>/opt/vendor/templates</filename>', and that you wish for
839 view scripts to be referenced by
840 '<filename>:moduleDir/:controller/:action.:suffix</filename>'; if the
841 <emphasis>noController</emphasis>
842 flag has been set, you want to render out of the top level
843 instead of in a subdirectory ('<filename>:action.:suffix</filename>'). Finally, you
844 want to use 'tpl' as the view script filename suffix.
847 <programlisting language="php"><![CDATA[
852 // Different view implementation
853 $view = new ZF_Smarty();
855 $viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer($view);
856 $viewRenderer->setViewBasePathSpec('/opt/vendor/templates')
857 ->setViewScriptPathSpec(':module/:controller/:action.:suffix')
858 ->setViewScriptPathNoControllerSpec(':action.:suffix')
859 ->setViewSuffix('tpl');
860 Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);
864 <example id="zend.controller.actionhelper.viewrenderer.advancedusage.example-2">
865 <title>Rendering Multiple View Scripts from a Single Action</title>
868 At times, you may need to render multiple view scripts from a
869 single action. This is very straightforward -- simply make
870 multiple calls to <methodname>render()</methodname>:
873 <programlisting language="php"><![CDATA[
874 class SearchController extends Zend_Controller_Action
876 public function resultsAction()
878 // Assume $this->model is the current model
879 $this->view->results =
880 $this->model->find($this->_getParam('query', '');
882 // render() by default proxies to the ViewRenderer
883 // Render first the search form and then the results
884 $this->render('form');
885 $this->render('results');
888 public function formAction()
890 // do nothing; ViewRenderer autorenders the view script