| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- Reviewed: no -->
- <sect1 id="learning.quickstart.create-layout">
- <title>Create A Layout</title>
- <para>
- You may have noticed that the view scripts in the previous sections were
- <acronym>HTML</acronym> fragments- not complete pages. This is by design; we want our
- actions to return content only related to the action itself, not the application as a whole.
- </para>
- <para>
- Now we must compose that generated content into a full <acronym>HTML</acronym> page. We'd
- also like to have a consistent look and feel for the application. We will use a global site
- layout to accomplish both of these tasks.
- </para>
- <para>
- There are two design patterns that Zend Framework uses to implement layouts: <ulink
- url="http://martinfowler.com/eaaCatalog/twoStepView.html">Two Step View</ulink> and
- <ulink
- url="http://www.oracle.com/technetwork/java/compositeview-137722.html">Composite
- View</ulink>. <emphasis>Two Step View</emphasis> is usually associated with the <ulink
- url="http://www.martinfowler.com/eaaCatalog/transformView.html">Transform View</ulink>
- pattern; the basic idea is that your application view creates a representation that is then
- injected into the master view for final transformation. The <emphasis>Composite
- View</emphasis> pattern deals with a view made of one or more atomic, application views.
- </para>
- <para>
- In Zend Framework, <link linkend="zend.layout">Zend_Layout</link> combines the ideas behind
- these patterns. Instead of each action view script needing to include site-wide artifacts,
- they can simply focus on their own responsibilities.
- </para>
- <para>
- Occasionally, however, you may need application-specific information in your site-wide view
- script. Fortunately, Zend Framework provides a variety of view
- <emphasis>placeholders</emphasis> to allow you to provide such information from your action
- view scripts.
- </para>
- <para>
- To get started using <classname>Zend_Layout</classname>, first we need to inform our
- bootstrap to use the <classname>Layout</classname> resource. This can be done using the
- <command>zf enable layout</command> command:
- </para>
- <programlisting language="shell"><![CDATA[
- % zf enable layout
- Layouts have been enabled, and a default layout created at
- application/layouts/scripts/layout.phtml
- A layout entry has been added to the application config file.
- ]]></programlisting>
- <para>
- As noted by the command,
- <filename>application/configs/application.ini</filename> is updated, and
- now contains the following within the <constant>production</constant>
- section:
- </para>
- <programlisting language="ini"><![CDATA[
- ; application/configs/application.ini
- ; Add to [production] section:
- resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts"
- ]]></programlisting>
- <para>
- The final <acronym>INI</acronym> file should look as follows:
- </para>
- <programlisting language="ini"><![CDATA[
- ; application/configs/application.ini
- [production]
- ; PHP settings we want to initialize
- phpSettings.display_startup_errors = 0
- phpSettings.display_errors = 0
- includePaths.library = APPLICATION_PATH "/../library"
- bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
- bootstrap.class = "Bootstrap"
- appnamespace = "Application"
- resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
- resources.frontController.params.displayExceptions = 0
- resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts"
- [staging : production]
- [testing : production]
- phpSettings.display_startup_errors = 1
- phpSettings.display_errors = 1
- [development : production]
- phpSettings.display_startup_errors = 1
- phpSettings.display_errors = 1
- ]]></programlisting>
- <para>
- This directive tells your application to look for layout view scripts in
- <filename>application/layouts/scripts</filename>. If you examine your directory tree, you'll
- see that this directory has been created for you now, with the file
- <filename>layout.phtml</filename>.
- </para>
- <para>
- We also want to ensure we have an XHTML DocType declaration for our application. To enable
- this, we need to add a resource to our bootstrap.
- </para>
- <para>
- The simplest way to add a bootstrap resource is to simply create a protected method
- beginning with the phrase <methodname>_init</methodname>. In this case, we want to
- initialize the doctype, so we'll create an <methodname>_initDoctype()</methodname> method
- within our bootstrap class:
- </para>
- <programlisting language="php"><![CDATA[
- // application/Bootstrap.php
- class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
- {
- protected function _initDoctype()
- {
- }
- }
- ]]></programlisting>
- <para>
- Within that method, we need to hint to the view to use the appropriate doctype. But where
- will the view object come from? The easy solution is to initialize the
- <classname>View</classname> resource; once we have, we can pull the view object from the
- bootstrap and use it.
- </para>
- <para>
- To initialize the view resource, add the following line to your
- <filename>application/configs/application.ini</filename> file, in the section marked
- <constant>production</constant>:
- </para>
- <programlisting language="ini"><![CDATA[
- ; application/configs/application.ini
- ; Add to [production] section:
- resources.view[] =
- ]]></programlisting>
- <para>
- This tells us to initialize the view with no options (the '[]' indicates that the "view" key
- is an array, and we pass nothing to it).
- </para>
- <para>
- Now that we have a view, let's flesh out our <methodname>_initDoctype()</methodname> method.
- In it, we will first ensure the <classname>View</classname> resource has run, fetch the view
- object, and then configure it:
- </para>
- <programlisting language="php"><![CDATA[
- // application/Bootstrap.php
- class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
- {
- protected function _initDoctype()
- {
- $this->bootstrap('view');
- $view = $this->getResource('view');
- $view->doctype('XHTML1_STRICT');
- }
- }
- ]]></programlisting>
- <para>
- Now that we've initialized <classname>Zend_Layout</classname> and set the Doctype, let's
- create our site-wide layout:
- </para>
- <programlisting language="php"><![CDATA[
- <!-- application/layouts/scripts/layout.phtml -->
- <?php echo $this->doctype() ?>
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>Zend Framework Quickstart Application</title>
- <?php echo $this->headLink()->appendStylesheet('/css/global.css') ?>
- </head>
- <body>
- <div id="header" style="background-color: #EEEEEE; height: 30px;">
- <div id="header-logo" style="float: left">
- <b>ZF Quickstart Application</b>
- </div>
- <div id="header-navigation" style="float: right">
- <a href="<?php echo $this->url(
- array('controller'=>'guestbook'),
- 'default',
- true) ?>">Guestbook</a>
- </div>
- </div>
- <?php echo $this->layout()->content ?>
- </body>
- </html>
- ]]></programlisting>
- <para>
- We grab our application content using the <methodname>layout()</methodname> view helper, and
- accessing the "content" key. You may render to other response segments if you wish to, but
- in most cases, this is all that's necessary.
- </para>
- <para>
- Note also the use of the <methodname>headLink()</methodname> placeholder. This is an easy
- way to generate the <acronym>HTML</acronym> for <link> elements, as well as to keep
- track of them throughout your application. If you need to add additional CSS sheets to
- support a single action, you can do so, and be assured it will be present in the final
- rendered page.
- </para>
- <note>
- <title>Checkpoint</title>
- <para>
- Now go to "http://localhost" and check out the source. You should see your XHTML header,
- head, title, and body sections.
- </para>
- </note>
- </sect1>
|