view-placeholders-standard.xml 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- Reviewed: no -->
  3. <sect1 id="learning.view.placeholders.standard">
  4. <title>Standard Placeholders</title>
  5. <para>
  6. In the <link linkend="learning.view.placeholders.basics">previous section</link>, we learned
  7. about the <methodname>placeholder()</methodname> view helper, and how it can be used to
  8. aggregate custom content. In this section, we'll look at some of the concrete placeholders
  9. shipped with Zend Framework, and how you can use them to your advantage when creating
  10. complex composite layouts.
  11. </para>
  12. <para>
  13. Most of the shipped placeholders are for generating content for the
  14. <emphasis>&lt;head&gt;</emphasis> section of your layout content -- an area you typically
  15. cannot manipulate directly via your application view scripts, but one you may want to
  16. influence. As examples: you may want your title to contain certain content on every page,
  17. but specific content based on the controller and/or action; you may want to specify
  18. <acronym>CSS</acronym> files to load based on what section of the application you're in; you
  19. may need specific JavaScript scripts loaded at different times; or you may want to set the
  20. <emphasis>DocType</emphasis> declaration.
  21. </para>
  22. <para>
  23. Zend Framework ships with placeholder implementations for each of these situations, and
  24. several more.
  25. </para>
  26. <sect2 id="learning.view.placeholders.standard.doctype">
  27. <title>Setting the DocType</title>
  28. <para>
  29. <emphasis>DocType</emphasis> declarations are troublesome to memorize, and often
  30. essential to include in your document to ensure the browser properly renders your
  31. content. The <methodname>doctype()</methodname> view helper allows you to use simple
  32. string mnemonics to specify the desired <emphasis>DocType</emphasis>; additionally,
  33. other helpers will query the <methodname>doctype()</methodname> helper to ensure the
  34. output generated conforms with the requested <emphasis>DocType</emphasis>.
  35. </para>
  36. <para>
  37. As an example, if you want to use the <acronym>XHTML1</acronym> Strict
  38. <acronym>DTD</acronym>, you can simply specify:
  39. </para>
  40. <programlisting language="php"><![CDATA[
  41. $this->doctype('XHTML1_STRICT');
  42. ]]></programlisting>
  43. <para>
  44. Among the other available mnemonics, you'll find these common types:
  45. </para>
  46. <variablelist>
  47. <varlistentry>
  48. <term>XHTML1_STRICT</term>
  49. <listitem>
  50. <para>
  51. <acronym>XHTML</acronym> 1.0 Strict
  52. </para>
  53. </listitem>
  54. </varlistentry>
  55. <varlistentry>
  56. <term>XHTML1_TRANSITIONAL</term>
  57. <listitem>
  58. <para>
  59. <acronym>XHTML</acronym> 1.0 Transitional
  60. </para>
  61. </listitem>
  62. </varlistentry>
  63. <varlistentry>
  64. <term>HTML4_STRICT</term>
  65. <listitem>
  66. <para>
  67. <acronym>HTML</acronym> 4.01 Strict
  68. </para>
  69. </listitem>
  70. </varlistentry>
  71. <varlistentry>
  72. <term>HTML4_Loose</term>
  73. <listitem>
  74. <para>
  75. <acronym>HTML</acronym> 4.01 Loose
  76. </para>
  77. </listitem>
  78. </varlistentry>
  79. <varlistentry>
  80. <term>HTML5</term>
  81. <listitem>
  82. <para>
  83. <acronym>HTML</acronym> 5
  84. </para>
  85. </listitem>
  86. </varlistentry>
  87. </variablelist>
  88. <para>
  89. You can assign the type and render the declaration in a single call:
  90. </para>
  91. <programlisting language="php"><![CDATA[
  92. echo $this->doctype('XHTML1_STRICT');
  93. ]]></programlisting>
  94. <para>
  95. However, the better approach is to assign the type in your bootstrap, and then render it
  96. in your layout. Try adding the following to your bootstrap class:
  97. </para>
  98. <programlisting language="php"><![CDATA[
  99. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  100. {
  101. protected function _initDocType()
  102. {
  103. $this->bootstrap('View');
  104. $view = $this->getResource('View');
  105. $view->doctype('XHTML1_STRICT');
  106. }
  107. }
  108. ]]></programlisting>
  109. <para>
  110. Then, in your layout script, simply <methodname>echo()</methodname> the helper at the
  111. top of the file:
  112. </para>
  113. <programlisting language="php"><![CDATA[
  114. <?php echo $this->doctype() ?>
  115. <html>
  116. <!-- ... -->
  117. ]]></programlisting>
  118. <para>
  119. This will ensure that your DocType-aware view helpers render the appropriate markup,
  120. ensure that the type is set well before the layout is rendered, and provide a single
  121. location to change the DocType.
  122. </para>
  123. </sect2>
  124. <sect2 id="learning.view.placeholders.standard.head-title">
  125. <title>Specifying the Page Title</title>
  126. <para>
  127. Often, a site will include the site or business name as part of the page title, and
  128. then add additional information based on the location within the site. As an example,
  129. the <filename>zend.com</filename> website includes the string
  130. "<filename>Zend.com</filename>" on all pages, and the prepends information based on the
  131. page: "Zend Server - <filename>Zend.com</filename>". Within Zend Framework, the
  132. <methodname>headTitle()</methodname> view helper can help simplify this task.
  133. </para>
  134. <para>
  135. At its simplest, the <methodname>headTitle()</methodname> helper allows you to aggregate
  136. content for the <emphasis>&lt;title&gt;</emphasis> tag; when you echo it, it then
  137. assembles it based on the order in which segments are added. You can control the order
  138. using <methodname>prepend()</methodname> and <methodname>append()</methodname>, and
  139. provide a separator to use between segments using the
  140. <methodname>setSeparator()</methodname> method.
  141. </para>
  142. <para>
  143. Typically, you should specify any segments common to all pages in your bootstrap,
  144. similar to how we define the doctype. In this case, we'll define a
  145. <methodname>_initPlaceholders()</methodname> method for operating on all the various
  146. placeholders, and specify an initial title as well as a separator.
  147. </para>
  148. <programlisting language="php"><![CDATA[
  149. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  150. {
  151. // ...
  152. protected function _initPlaceholders()
  153. {
  154. $this->bootstrap('View');
  155. $view = $this->getResource('View');
  156. $view->doctype('XHTML1_STRICT');
  157. // Set the initial title and separator:
  158. $view->headTitle('My Site')
  159. ->setSeparator(' :: ');
  160. }
  161. // ...
  162. }
  163. ]]></programlisting>
  164. <para>
  165. Within a view script, we might want to add another segment:
  166. </para>
  167. <programlisting language="php"><![CDATA[
  168. <?php $this->headTitle()->append('Some Page'); // place after other segments ?>
  169. <?php $this->headTitle()->prepend('Some Page'); // place before ?>
  170. ]]></programlisting>
  171. <para>
  172. In our layout, we will simply echo the <methodname>headTitle()</methodname> helper:
  173. </para>
  174. <programlisting language="php"><![CDATA[
  175. <?php echo $this->doctype() ?>
  176. <html>
  177. <?php echo $this->headTitle() ?>
  178. <!-- ... -->
  179. ]]></programlisting>
  180. <para>
  181. This will generate the following output:
  182. </para>
  183. <programlisting language="html"><![CDATA[
  184. <!-- If append() was used: -->
  185. <title>My Site :: Some Page</title>
  186. <!-- If prepend() was used: -->
  187. <title>Some Page :: My Site</title>
  188. ]]></programlisting>
  189. </sect2>
  190. <sect2 id="learning.view.placeholders.standard.head-link">
  191. <title>Specifying Stylesheets with HeadLink</title>
  192. <para>
  193. Good <acronym>CSS</acronym> developers will often create a general stylesheet for
  194. sitewide styles, and individual stylesheets for specific sections or pages of the
  195. website, and load these latter conditionally so as to decrease the amount of data
  196. needing to be transferred on each request. The <methodname>headLink()</methodname>
  197. placeholder makes such conditional aggregation of stylesheets trivial within your
  198. application.
  199. </para>
  200. <para>
  201. To accomplish this, <methodname>headLink()</methodname> defines a number of "virtual"
  202. methods (via overloading) to make the process trivial. The ones we will be concerned
  203. with are <methodname>appendStylesheet()</methodname> and
  204. <methodname>prependStylesheet()</methodname>. Each takes up to four arguments,
  205. <varname>$href</varname> (the relative path to the stylesheet),
  206. <varname>$media</varname> (the <acronym>MIME</acronym> type, which defaults to
  207. "text/css"), <varname>$conditionalStylesheet</varname> (which can be used to specify a
  208. "condition" under which the stylesheet will be evaluated), and
  209. <varname>$extras</varname> (an associative array of key and value pairs, commonly used
  210. to specify a key for "media"). In most cases, you will only need to specify the first
  211. argument, the relative path to the stylesheet.
  212. </para>
  213. <para>
  214. In our example, we'll assume that all pages need to load the stylesheet located in
  215. "<filename>/styles/site.css</filename>" (relative to the document root); we'll specify
  216. this in our <methodname>_initPlaceholders()</methodname> bootstrap method.
  217. </para>
  218. <programlisting language="php"><![CDATA[
  219. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  220. {
  221. // ...
  222. protected function _initPlaceholders()
  223. {
  224. $this->bootstrap('View');
  225. $view = $this->getResource('View');
  226. $view->doctype('XHTML1_STRICT');
  227. // Set the initial title and separator:
  228. $view->headTitle('My Site')
  229. ->setSeparator(' :: ');
  230. // Set the initial stylesheet:
  231. $view->headLink()->prependStylesheet('/styles/site.css');
  232. }
  233. // ...
  234. }
  235. ]]></programlisting>
  236. <para>
  237. Later, in a controller or action-specific view script, we can add more stylesheets:
  238. </para>
  239. <programlisting language="php"><![CDATA[
  240. <?php $this->headLink()->appendStylesheet('/styles/user-list.css') ?>
  241. ]]></programlisting>
  242. <para>
  243. Within our layout view script, once again, we simply echo the placeholder:
  244. </para>
  245. <programlisting language="php"><![CDATA[
  246. <?php echo $this->doctype() ?>
  247. <html>
  248. <?php echo $this->headTitle() ?>
  249. <?php echo $this->headLink() ?>
  250. <!-- ... -->
  251. ]]></programlisting>
  252. <para>
  253. This will generate the following output:
  254. </para>
  255. <programlisting language="html"><![CDATA[
  256. <link rel="stylesheet" type="text/css" href="/styles/site.css" />
  257. <link rel="stylesheet" type="text/css" href="/styles/user-list.css" />
  258. ]]></programlisting>
  259. </sect2>
  260. <sect2 id="learning.view.placeholders.standard.head-script">
  261. <title>Aggregating Scripts Using HeadScript</title>
  262. <para>
  263. Another common tactic to prevent long page load times is to only load JavaScript when
  264. necessary. That said, you may need several layers of scripts: perhaps one for
  265. progressively enhancing menus on the site, and another for page-specific content. In
  266. these situations, the <methodname>headScript()</methodname> helper presents a solution.
  267. </para>
  268. <para>
  269. Similar to the <methodname>headLink()</methodname> helper,
  270. <methodname>headScript()</methodname> provides the ability to append or prepend scripts
  271. to the collection, and then echo the entire set. It provides the flexibility to specify
  272. either script files themselves to load, or explicit JavaScript. You also have the option
  273. of capturing JavaScript via
  274. <methodname>captureStart()</methodname>/<methodname>captureEnd()</methodname>, which
  275. allows you to simply inline the JavaScript instead of requiring an additional call to
  276. your server.
  277. </para>
  278. <para>
  279. Also like <methodname>headLink()</methodname>, <methodname>headScript()</methodname>
  280. provides "virtual" methods via overloading as a convenience when specifying items to
  281. aggregate; common methods include <methodname>prependFile()</methodname>,
  282. <methodname>appendFile()</methodname>, <methodname>prependScript()</methodname>, and
  283. <methodname>appendScript()</methodname>. The first two allow you to specify files that
  284. will be referenced in a <emphasis>&lt;script&gt;</emphasis> tag's
  285. <varname>$src</varname> attribute; the latter two will take the content provided and
  286. render it as literal JavaScript within a <emphasis>&lt;script&gt;</emphasis> tag.
  287. </para>
  288. <para>
  289. In this example, we'll specify that a script, "<filename>/js/site.js</filename>" needs
  290. to be loaded on every page; we'll update our
  291. <methodname>_initPlaceholders()</methodname> bootstrap method to do this.
  292. </para>
  293. <programlisting language="php"><![CDATA[
  294. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  295. {
  296. // ...
  297. protected function _initPlaceholders()
  298. {
  299. $this->bootstrap('View');
  300. $view = $this->getResource('View');
  301. $view->doctype('XHTML1_STRICT');
  302. // Set the initial title and separator:
  303. $view->headTitle('My Site')
  304. ->setSeparator(' :: ');
  305. // Set the initial stylesheet:
  306. $view->headLink()->prependStylesheet('/styles/site.css');
  307. // Set the initial JS to load:
  308. $view->headScript()->prependFile('/js/site.js');
  309. }
  310. // ...
  311. }
  312. ]]></programlisting>
  313. <para>
  314. Within a view script, we might then add an extra script file to source, or capture some
  315. JavaScript to include in our document.
  316. </para>
  317. <programlisting language="php"><![CDATA[
  318. <?php $this->headScript()->appendFile('/js/user-list.js') ?>
  319. <?php $this->headScript()->captureStart() ?>
  320. site = {
  321. baseUrl: "<?php echo $this->baseUrl() ?>"
  322. };
  323. <?php $this->headScript()->captureEnd() ?>
  324. ]]></programlisting>
  325. <para>
  326. Within our layout script, we then simply echo the placeholder, just as we have all the
  327. others:
  328. </para>
  329. <programlisting language="php"><![CDATA[
  330. <?php echo $this->doctype() ?>
  331. <html>
  332. <?php echo $this->headTitle() ?>
  333. <?php echo $this->headLink() ?>
  334. <?php echo $this->headScript() ?>
  335. <!-- ... -->
  336. ]]></programlisting>
  337. <para>
  338. This will generate the following output:
  339. </para>
  340. <programlisting language="html"><![CDATA[
  341. <script type="text/javascript" src="/js/site.js"></script>
  342. <script type="text/javascript" src="/js/user-list.js"></script>
  343. <script type="text/javascript">
  344. site = {
  345. baseUrl: "<?php echo $this->baseUrl() ?>"
  346. };
  347. </script>
  348. ]]></programlisting>
  349. <note>
  350. <title>InlineScript Variant</title>
  351. <para>
  352. Many browsers will often block display of a page until all scripts and stylesheets
  353. referenced in the <emphasis>&lt;head&gt;</emphasis> section have loaded. If you have
  354. a number of such directives, this can impact how soon somebody can start actually
  355. viewing the page.
  356. </para>
  357. <para>
  358. One way around this is to emit your <emphasis>&lt;script&gt;</emphasis> tags just
  359. prior to closing the <emphasis>&lt;body&gt;</emphasis> of your document. (This is a
  360. practice specifically recommend by the <ulink
  361. url="http://developer.yahoo.com/yslow/">Y! Slow project</ulink>.)
  362. </para>
  363. <para>
  364. Zend Framework supports this in two different ways:
  365. </para>
  366. <itemizedlist>
  367. <listitem>
  368. <para>
  369. You can render your <methodname>headScript()</methodname> tag whereever you
  370. like in your layout script; just because the title references "head" does
  371. not mean it needs to be rendered in that location.
  372. </para>
  373. </listitem>
  374. <listitem>
  375. <para>
  376. Alternately, you may use the <methodname>inlineScript()</methodname> helper,
  377. which is simply a variant on <methodname>headScript()</methodname>, and
  378. retains the same behavior, but uses a separate registry.
  379. </para>
  380. </listitem>
  381. </itemizedlist>
  382. </note>
  383. </sect2>
  384. </sect1>