quickstart-create-layout.xml 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- Reviewed: no -->
  3. <sect1 id="learning.quickstart.create-layout">
  4. <title>Create A Layout</title>
  5. <para>
  6. You may have noticed that the view scripts in the previous sections were
  7. <acronym>HTML</acronym> fragments- not complete pages. This is by design; we want our
  8. actions to return content only related to the action itself, not the application as a whole.
  9. </para>
  10. <para>
  11. Now we must compose that generated content into a full <acronym>HTML</acronym> page. We'd
  12. also like to have a consistent look and feel for the application. We will use a global site
  13. layout to accomplish both of these tasks.
  14. </para>
  15. <para>
  16. There are two design patterns that Zend Framework uses to implement layouts: <ulink
  17. url="http://martinfowler.com/eaaCatalog/twoStepView.html">Two Step View</ulink> and
  18. <ulink
  19. url="http://www.oracle.com/technetwork/java/compositeview-137722.html">Composite
  20. View</ulink>. <emphasis>Two Step View</emphasis> is usually associated with the <ulink
  21. url="http://www.martinfowler.com/eaaCatalog/transformView.html">Transform View</ulink>
  22. pattern; the basic idea is that your application view creates a representation that is then
  23. injected into the master view for final transformation. The <emphasis>Composite
  24. View</emphasis> pattern deals with a view made of one or more atomic, application views.
  25. </para>
  26. <para>
  27. In Zend Framework, <link linkend="zend.layout">Zend_Layout</link> combines the ideas behind
  28. these patterns. Instead of each action view script needing to include site-wide artifacts,
  29. they can simply focus on their own responsibilities.
  30. </para>
  31. <para>
  32. Occasionally, however, you may need application-specific information in your site-wide view
  33. script. Fortunately, Zend Framework provides a variety of view
  34. <emphasis>placeholders</emphasis> to allow you to provide such information from your action
  35. view scripts.
  36. </para>
  37. <para>
  38. To get started using <classname>Zend_Layout</classname>, first we need to inform our
  39. bootstrap to use the <classname>Layout</classname> resource. This can be done using the
  40. <command>zf enable layout</command> command:
  41. </para>
  42. <programlisting language="shell"><![CDATA[
  43. % zf enable layout
  44. Layouts have been enabled, and a default layout created at
  45. application/layouts/scripts/layout.phtml
  46. A layout entry has been added to the application config file.
  47. ]]></programlisting>
  48. <para>
  49. As noted by the command,
  50. <filename>application/configs/application.ini</filename> is updated, and
  51. now contains the following within the <constant>production</constant>
  52. section:
  53. </para>
  54. <programlisting language="ini"><![CDATA[
  55. ; application/configs/application.ini
  56. ; Add to [production] section:
  57. resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts"
  58. ]]></programlisting>
  59. <para>
  60. The final <acronym>INI</acronym> file should look as follows:
  61. </para>
  62. <programlisting language="ini"><![CDATA[
  63. ; application/configs/application.ini
  64. [production]
  65. ; PHP settings we want to initialize
  66. phpSettings.display_startup_errors = 0
  67. phpSettings.display_errors = 0
  68. includePaths.library = APPLICATION_PATH "/../library"
  69. bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
  70. bootstrap.class = "Bootstrap"
  71. appnamespace = "Application"
  72. resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
  73. resources.frontController.params.displayExceptions = 0
  74. resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts"
  75. [staging : production]
  76. [testing : production]
  77. phpSettings.display_startup_errors = 1
  78. phpSettings.display_errors = 1
  79. [development : production]
  80. phpSettings.display_startup_errors = 1
  81. phpSettings.display_errors = 1
  82. ]]></programlisting>
  83. <para>
  84. This directive tells your application to look for layout view scripts in
  85. <filename>application/layouts/scripts</filename>. If you examine your directory tree, you'll
  86. see that this directory has been created for you now, with the file
  87. <filename>layout.phtml</filename>.
  88. </para>
  89. <para>
  90. We also want to ensure we have an XHTML DocType declaration for our application. To enable
  91. this, we need to add a resource to our bootstrap.
  92. </para>
  93. <para>
  94. The simplest way to add a bootstrap resource is to simply create a protected method
  95. beginning with the phrase <methodname>_init</methodname>. In this case, we want to
  96. initialize the doctype, so we'll create an <methodname>_initDoctype()</methodname> method
  97. within our bootstrap class:
  98. </para>
  99. <programlisting language="php"><![CDATA[
  100. // application/Bootstrap.php
  101. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  102. {
  103. protected function _initDoctype()
  104. {
  105. }
  106. }
  107. ]]></programlisting>
  108. <para>
  109. Within that method, we need to hint to the view to use the appropriate doctype. But where
  110. will the view object come from? The easy solution is to initialize the
  111. <classname>View</classname> resource; once we have, we can pull the view object from the
  112. bootstrap and use it.
  113. </para>
  114. <para>
  115. To initialize the view resource, add the following line to your
  116. <filename>application/configs/application.ini</filename> file, in the section marked
  117. <constant>production</constant>:
  118. </para>
  119. <programlisting language="ini"><![CDATA[
  120. ; application/configs/application.ini
  121. ; Add to [production] section:
  122. resources.view[] =
  123. ]]></programlisting>
  124. <para>
  125. This tells us to initialize the view with no options (the '[]' indicates that the "view" key
  126. is an array, and we pass nothing to it).
  127. </para>
  128. <para>
  129. Now that we have a view, let's flesh out our <methodname>_initDoctype()</methodname> method.
  130. In it, we will first ensure the <classname>View</classname> resource has run, fetch the view
  131. object, and then configure it:
  132. </para>
  133. <programlisting language="php"><![CDATA[
  134. // application/Bootstrap.php
  135. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  136. {
  137. protected function _initDoctype()
  138. {
  139. $this->bootstrap('view');
  140. $view = $this->getResource('view');
  141. $view->doctype('XHTML1_STRICT');
  142. }
  143. }
  144. ]]></programlisting>
  145. <para>
  146. Now that we've initialized <classname>Zend_Layout</classname> and set the Doctype, let's
  147. create our site-wide layout:
  148. </para>
  149. <programlisting language="php"><![CDATA[
  150. <!-- application/layouts/scripts/layout.phtml -->
  151. <?php echo $this->doctype() ?>
  152. <html xmlns="http://www.w3.org/1999/xhtml">
  153. <head>
  154. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  155. <title>Zend Framework Quickstart Application</title>
  156. <?php echo $this->headLink()->appendStylesheet('/css/global.css') ?>
  157. </head>
  158. <body>
  159. <div id="header" style="background-color: #EEEEEE; height: 30px;">
  160. <div id="header-logo" style="float: left">
  161. <b>ZF Quickstart Application</b>
  162. </div>
  163. <div id="header-navigation" style="float: right">
  164. <a href="<?php echo $this->url(
  165. array('controller'=>'guestbook'),
  166. 'default',
  167. true) ?>">Guestbook</a>
  168. </div>
  169. </div>
  170. <?php echo $this->layout()->content ?>
  171. </body>
  172. </html>
  173. ]]></programlisting>
  174. <para>
  175. We grab our application content using the <methodname>layout()</methodname> view helper, and
  176. accessing the "content" key. You may render to other response segments if you wish to, but
  177. in most cases, this is all that's necessary.
  178. </para>
  179. <para>
  180. Note also the use of the <methodname>headLink()</methodname> placeholder. This is an easy
  181. way to generate the <acronym>HTML</acronym> for &lt;link&gt; elements, as well as to keep
  182. track of them throughout your application. If you need to add additional CSS sheets to
  183. support a single action, you can do so, and be assured it will be present in the final
  184. rendered page.
  185. </para>
  186. <note>
  187. <title>Checkpoint</title>
  188. <para>
  189. Now go to "http://localhost" and check out the source. You should see your XHTML header,
  190. head, title, and body sections.
  191. </para>
  192. </note>
  193. </sect1>