Zend_View-Scripts.xml 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- Reviewed: no -->
  3. <sect1 id="zend.view.scripts">
  4. <title>Скрипты видов</title>
  5. <para>
  6. После того, как ваш контроллер определил переменные и вызвал
  7. метод <code>render()</code>, <classname>Zend_View</classname> включает
  8. требуемый скрипт вида и выполняет его в области
  9. видимости экземпляра <classname>Zend_View</classname>. Поэтому в вашем скрипте
  10. вида ссылки на $this в действительности будут ссылаться на
  11. сам экземляр <classname>Zend_View</classname>.
  12. </para>
  13. <para>
  14. Переменные, устанавливаемые в контроллере для скрипта вида, являются
  15. свойствами экземпляра <classname>Zend_View</classname>. Например, если контроллер
  16. установил переменную 'something', то в скрипте вида вы можете ссылаться
  17. на нее следующим образом: <varname>$this->something</varname>. Это дает
  18. возможность отслеживать, какие переменные были установлены
  19. извне для скрипта, и какие были установлены в самом скрипте.
  20. </para>
  21. <para>
  22. Ниже приведен пример скрипта вида из введения:
  23. </para>
  24. <programlisting language="php"><![CDATA[
  25. <?php if ($this->books): ?>
  26. <!-- Таблица из нескольких книг. -->
  27. <table>
  28. <tr>
  29. <th>Author</th>
  30. <th>Title</th>
  31. </tr>
  32. <?php foreach ($this->books as $key => $val): ?>
  33. <tr>
  34. <td><?php echo $this->escape($val['author']) ?></td>
  35. <td><?php echo $this->escape($val['title']) ?></td>
  36. </tr>
  37. <?php endforeach; ?>
  38. </table>
  39. <?php else: ?>
  40. <p>Нет книг для отображения.</p>
  41. <?php endif;?>
  42. ]]></programlisting>
  43. <sect2 id="zend.view.scripts.escaping">
  44. <title>Экранирование вывода</title>
  45. <para>
  46. Одной из наиважнейших задач, которую должен решать скрипт вида,
  47. является обеспечение того, что вывод должным образом
  48. экранирован; помимо прочего, это помогает
  49. предотвратить XSS-атаки.
  50. За исключением тех случаев, когда используются функции,
  51. методы или помощники, которые сами производят экранирование,
  52. вы должны всегда экранировать переменные, когда выводите их.
  53. </para>
  54. <para>
  55. <classname>Zend_View</classname> снабжен методом <code>escape()</code>,
  56. который выполняет экранирование.
  57. </para>
  58. <programlisting language="php"><![CDATA[
  59. // плохая практика
  60. echo $this->variable;
  61. // хорошая практика
  62. echo $this->escape($this->variable);
  63. ]]></programlisting>
  64. <para>
  65. По умолчанию метод <code>escape()</code> использует функцию PHP
  66. <code>htmlspecialchars()</code> для экранирования. Но, в зависимости
  67. от вашего окружения, может потребоваться выполнять экранирование
  68. по-иному. Используйте метод <code>setEscape()</code> на уровне
  69. контроллера, чтобы указать <classname>Zend_View</classname>, какую
  70. экранирующую функцию обратного вызова использовать.
  71. </para>
  72. <programlisting language="php"><![CDATA[
  73. // создание экземпляра Zend_View
  74. $view = new Zend_View();
  75. // приказываем ему использовать htmlentities
  76. // в качестве экранирующей функции обратного вызова
  77. $view->setEscape('htmlentities');
  78. // либо приказываем ему использовать статический метод класса
  79. $view->setEscape(array('SomeClass', 'methodName'));
  80. // или даже метод экземпляра
  81. $obj = new SomeClass();
  82. $view->setEscape(array($obj, 'methodName'));
  83. // и затем воспроизводим вид
  84. echo $view->render(...);
  85. ]]></programlisting>
  86. <para>
  87. Функции или методы обратного вызова должны принимать значение,
  88. которое требуется экранировать, как первый параметр,
  89. все остальные параметры должны быть необязательными.
  90. </para>
  91. </sect2>
  92. <sect2 id="zend.view.scripts.templates">
  93. <title>Использование других шаблонизаторов</title>
  94. <para>
  95. Хотя PHP сам по себе представляет собой мощный шаблонизатор,
  96. многие разработчики считают его избыточным или сложным для
  97. верстальщиков и предпочитают использовать другие
  98. шаблонизаторы. <classname>Zend_View</classname> предоставляет два пути для
  99. этого: первый - через скрипты вида, второй - посредством реализации
  100. интерфейса <classname>Zend_View_Interface</classname>.
  101. </para>
  102. <sect3 id="zend.view.scripts.templates.scripts">
  103. <title>Шаблонизаторы c использованием скриптов видов</title>
  104. <para>
  105. Скрипт вида может использоваться для инстанцирования и
  106. манипулирования отдельным объектом шаблона (это могут быть
  107. шаблоны в стиле PHPLIB).
  108. </para>
  109. <programlisting language="php"><![CDATA[
  110. include_once 'template.inc';
  111. $tpl = new Template();
  112. if ($this->books) {
  113. $tpl->setFile(array(
  114. "booklist" => "booklist.tpl",
  115. "eachbook" => "eachbook.tpl",
  116. ));
  117. foreach ($this->books as $key => $val) {
  118. $tpl->set_var('author', $this->escape($val['author']);
  119. $tpl->set_var('title', $this->escape($val['title']);
  120. $tpl->parse("books", "eachbook", true);
  121. }
  122. $tpl->pparse("output", "booklist");
  123. } else {
  124. $tpl->setFile("nobooks", "nobooks.tpl")
  125. $tpl->pparse("output", "nobooks");
  126. }
  127. ]]></programlisting>
  128. <para>
  129. Это может соответствовать следующему файлу шаблона:
  130. </para>
  131. <programlisting language="html"><![CDATA[
  132. <!-- booklist.tpl -->
  133. <table>
  134. <tr>
  135. <th>Author</th>
  136. <th>Title</th>
  137. </tr>
  138. {books}
  139. </table>
  140. <!-- eachbook.tpl -->
  141. <tr>
  142. <td>{author}</td>
  143. <td>{title}</td>
  144. </tr>
  145. <!-- nobooks.tpl -->
  146. <p>Нет книг для отображения.</p>
  147. ]]></programlisting>
  148. </sect3>
  149. <sect3 id="zend.view.scripts.templates.interface">
  150. <title>Шаблонизаторы с использованием Zend_View_Interface</title>
  151. <para>
  152. Некоторые считают более удобным использовать совместимый с
  153. <classname>Zend_View</classname> шаблонизатор.
  154. <classname>Zend_View_Interface</classname>
  155. предоставляет минимально необходимый для
  156. совместимости интерфейс:
  157. </para>
  158. <programlisting language="php"><![CDATA[
  159. /**
  160. * Возвращает объект используемого шаблонизатора
  161. */
  162. public function getEngine();
  163. /**
  164. * Устанавливает путь к шаблонам или скриптам вида
  165. */
  166. public function setScriptPath($path);
  167. /**
  168. * Устанавливает базовый путь ко всем необходимым скрипту вида ресурсам
  169. */
  170. public function setBasePath($path, $prefix = 'Zend_View');
  171. /**
  172. * Устанавливает дополнительный базовый путь к необходимым скрипту вида ресурсам
  173. */
  174. public function addBasePath($path, $prefix = 'Zend_View');
  175. /**
  176. * Возвращает текущие пути к скриптам
  177. */
  178. public function getScriptPaths();
  179. /**
  180. * Переопределение методов для присвоения значений переменным шаблонов как
  181. * свойствам объекта
  182. */
  183. public function __set($key, $value);
  184. public function __get($key);
  185. public function __isset($key);
  186. public function __unset($key);
  187. /**
  188. * "Ручная" установка значения переменной шаблона или одновременное присвоение
  189. * значений нескольким переменным
  190. */
  191. public function assign($spec, $value = null);
  192. /**
  193. * Удаление всех переменных шаблона
  194. */
  195. public function clearVars();
  196. /**
  197. * Вывод шаблона с именем $name
  198. */
  199. public function render($name);
  200. ]]></programlisting>
  201. <para>
  202. Используя этот интерфейс, относительно легко сделать "обертку"
  203. для шаблонизаторов сторонних разработчиков. В примере показан
  204. вариант "обертки" для Smarty:
  205. </para>
  206. <programlisting language="php"><![CDATA[
  207. class Zend_View_Smarty implements Zend_View_Interface
  208. {
  209. /**
  210. * Объект Smarty
  211. * @var Smarty
  212. */
  213. protected $_smarty;
  214. /**
  215. * Конструктор
  216. *
  217. * @param string $tmplPath
  218. * @param array $extraParams
  219. * @return void
  220. */
  221. public function __construct($tmplPath = null, $extraParams = array())
  222. {
  223. $this->_smarty = new Smarty;
  224. if (null !== $tmplPath) {
  225. $this->setScriptPath($tmplPath);
  226. }
  227. foreach ($extraParams as $key => $value) {
  228. $this->_smarty->$key = $value;
  229. }
  230. }
  231. /**
  232. * Возвращение объекта шаблонизатора
  233. *
  234. * @return Smarty
  235. */
  236. public function getEngine()
  237. {
  238. return $this->_smarty;
  239. }
  240. /**
  241. * Установка пути к шаблонам
  242. *
  243. * @param string $path Директория, устанавливаемая как путь к шаблонам
  244. * @return void
  245. */
  246. public function setScriptPath($path)
  247. {
  248. if (is_readable($path)) {
  249. $this->_smarty->template_dir = $path;
  250. return;
  251. }
  252. throw new Exception('Invalid path provided');
  253. }
  254. /**
  255. * Извлечение текущего пути к шаблонам
  256. *
  257. * @return string
  258. */
  259. public function getScriptPaths()
  260. {
  261. return array($this->_smarty->template_dir);
  262. }
  263. /**
  264. * Метод-"псевдоним" для setScriptPath
  265. *
  266. * @param string $path
  267. * @param string $prefix Не используется
  268. * @return void
  269. */
  270. public function setBasePath($path, $prefix = 'Zend_View')
  271. {
  272. return $this->setScriptPath($path);
  273. }
  274. /**
  275. * Метод-"псевдоним" для setScriptPath
  276. *
  277. * @param string $path
  278. * @param string $prefix Не используется
  279. * @return void
  280. */
  281. public function addBasePath($path, $prefix = 'Zend_View')
  282. {
  283. return $this->setScriptPath($path);
  284. }
  285. /**
  286. * Присвоение значения переменной шаблона
  287. *
  288. * @param string $key Имя переменной
  289. * @param mixed $val Значение переменной
  290. * @return void
  291. */
  292. public function __set($key, $val)
  293. {
  294. $this->_smarty->assign($key, $val);
  295. }
  296. /**
  297. * Получение значения переменной
  298. *
  299. * @param string $key Имя переменной
  300. * @return mixed Значение переменной
  301. */
  302. public function __get($key)
  303. {
  304. return $this->_smarty->get_template_vars($key);
  305. }
  306. /**
  307. * Позволяет проверять переменные через empty() и isset()
  308. *
  309. * @param string $key
  310. * @return boolean
  311. */
  312. public function __isset($key)
  313. {
  314. return (null !== $this->_smarty->get_template_vars($key));
  315. }
  316. /**
  317. * Позволяет удалять свойства объекта через unset()
  318. *
  319. * @param string $key
  320. * @return void
  321. */
  322. public function __unset($key)
  323. {
  324. $this->_smarty->clear_assign($key);
  325. }
  326. /**
  327. * Присвоение переменных шаблону
  328. *
  329. * Позволяет установить значение к определенному ключу или передать массив
  330. * пар ключ => значение
  331. *
  332. * @see __set()
  333. * @param string|array $spec Ключ или массив пар ключ => значение
  334. * @param mixed $value (необязательный) Если присваивается значение одной
  335. * переменной, то через него передается значение переменной
  336. * @return void
  337. */
  338. public function assign($spec, $value = null)
  339. {
  340. if (is_array($spec)) {
  341. $this->_smarty->assign($spec);
  342. return;
  343. }
  344. $this->_smarty->assign($spec, $value);
  345. }
  346. /**
  347. * Удаление всех переменных
  348. *
  349. * @return void
  350. */
  351. public function clearVars()
  352. {
  353. $this->_smarty->clear_all_assign();
  354. }
  355. /**
  356. * Обрабатывает шаблон и возвращает вывод
  357. *
  358. * @param string $name Шаблон для обработки
  359. * @return string Вывод
  360. */
  361. public function render($name)
  362. {
  363. return $this->_smarty->fetch($name);
  364. }
  365. }
  366. ]]></programlisting>
  367. <para>
  368. В этом примере вы можете инстанцировать класс
  369. <classname>Zend_View_Smarty</classname> вместо <classname>Zend_View</classname> и
  370. использовать его так же, как используется
  371. <classname>Zend_View</classname>.
  372. </para>
  373. <programlisting language="php"><![CDATA[
  374. //Пример 1. В initView() инициализатора
  375. $view = new Zend_View_Smarty('/path/to/templates');
  376. $viewRenderer =
  377. new Zend_Controller_Action_HelperBroker::getStaticHelper('ViewRenderer');
  378. $viewRenderer->setView($view)
  379. ->setViewBasePathSpec($view->_smarty->template_dir)
  380. ->setViewScriptPathSpec(':controller/:action.:suffix')
  381. ->setViewScriptPathNoControllerSpec(':action.:suffix')
  382. ->setViewSuffix('tpl');
  383. //Пример 2. Использование в контроллере действии остается тем же
  384. class FooController extends Zend_Controller_Action
  385. {
  386. public function barAction()
  387. {
  388. $this->view->book = 'Zend PHP 5 Certification Study Guide';
  389. $this->view->author = 'Davey Shafik and Ben Ramsey'
  390. }
  391. }
  392. //Пример 3. Инициализация вида в контроллере действий
  393. class FooController extends Zend_Controller_Action
  394. {
  395. public function init()
  396. {
  397. $this->view = new Zend_View_Smarty('/path/to/templates');
  398. $viewRenderer = $this->_helper->getHelper('viewRenderer');
  399. $viewRenderer->setView($this->view)
  400. ->setViewBasePathSpec($view->_smarty->template_dir)
  401. ->setViewScriptPathSpec(':controller/:action.:suffix')
  402. ->setViewScriptPathNoControllerSpec(':action.:suffix')
  403. ->setViewSuffix('tpl');
  404. }
  405. }
  406. ]]></programlisting>
  407. </sect3>
  408. </sect2>
  409. </sect1>
  410. <!--
  411. vim:se ts=4 sw=4 et:
  412. -->