Главная / Zend Manual Core
Скрипты контроллеров

Скрипты видов

После того, как ваш контроллер определил переменные и вызвал метод render(), Zend_View включает требуемый скрипт вида и выполняет его в области видимости экземпляра Zend_View. Поэтому в вашем скрипте вида ссылки на $this в действительности будут ссылаться на сам экземляр Zend_View.

Переменные, устанавливаемые в контроллере для скрипта вида, являются свойствами экземпляра Zend_View. Например, если контроллер установил переменную 'something', то в скрипте вида вы можете ссылаться на нее следующим образом: $this->something. Это дает возможность отслеживать, какие переменные были установлены извне для скрипта, и какие были установлены в самом скрипте.

Ниже приведен пример скрипта вида из введения:

  1. <?php if ($this->books): ?>
  2.  
  3.     <!-- Таблица из нескольких книг. -->
  4.     <table>
  5.         <tr>
  6.             <th>Author</th>
  7.             <th>Title</th>
  8.         </tr>
  9.  
  10.         <?php foreach ($this->books as $key => $val): ?>
  11.         <tr>
  12.             <td><?php echo $this->escape($val['author']) ?></td>
  13.             <td><?php echo $this->escape($val['title']) ?></td>
  14.         </tr>
  15.         <?php endforeach; ?>
  16.  
  17.     </table>
  18.  
  19. <?php else: ?>
  20.  
  21.     <p>Нет книг для отображения.</p>
  22.  
  23. <?php endif;?>

Экранирование вывода

Одной из наиважнейших задач, которую должен решать скрипт вида, является обеспечение того, что вывод должным образом экранирован; помимо прочего, это помогает предотвратить XSS-атаки. За исключением тех случаев, когда используются функции, методы или помощники, которые сами производят экранирование, вы должны всегда экранировать переменные, когда выводите их.

Zend_View снабжен методом escape(), который выполняет экранирование.

  1. // плохая практика
  2. echo $this->variable;
  3.  
  4. // хорошая практика
  5. echo $this->escape($this->variable);

По умолчанию метод escape() использует функцию PHP htmlspecialchars() для экранирования. Но, в зависимости от вашего окружения, может потребоваться выполнять экранирование по-иному. Используйте метод setEscape() на уровне контроллера, чтобы указать Zend_View, какую экранирующую функцию обратного вызова использовать.

  1. // создание экземпляра Zend_View
  2. $view = new Zend_View();
  3.  
  4. // приказываем ему использовать htmlentities
  5. // в качестве экранирующей функции обратного вызова
  6. $view->setEscape('htmlentities');
  7.  
  8. // либо приказываем ему использовать статический метод класса
  9. $view->setEscape(array('SomeClass', 'methodName'));
  10.  
  11. // или даже метод экземпляра
  12. $obj = new SomeClass();
  13. $view->setEscape(array($obj, 'methodName'));
  14.  
  15. // и затем воспроизводим вид
  16. echo $view->render(...);

Функции или методы обратного вызова должны принимать значение, которое требуется экранировать, как первый параметр, все остальные параметры должны быть необязательными.

Использование других шаблонизаторов

Хотя PHP сам по себе представляет собой мощный шаблонизатор, многие разработчики считают его избыточным или сложным для верстальщиков и предпочитают использовать другие шаблонизаторы. Zend_View предоставляет два пути для этого: первый - через скрипты вида, второй - посредством реализации интерфейса Zend_View_Interface.

Шаблонизаторы c использованием скриптов видов

Скрипт вида может использоваться для инстанцирования и манипулирования отдельным объектом шаблона (это могут быть шаблоны в стиле PHPLIB).

  1. include_once 'template.inc';
  2. $tpl = new Template();
  3.  
  4. if ($this->books) {
  5.     $tpl->setFile(array(
  6.         "booklist" => "booklist.tpl",
  7.         "eachbook" => "eachbook.tpl",
  8.     ));
  9.  
  10.     foreach ($this->books as $key => $val) {
  11.         $tpl->set_var('author', $this->escape($val['author']);
  12.         $tpl->set_var('title', $this->escape($val['title']);
  13.         $tpl->parse("books", "eachbook", true);
  14.     }
  15.  
  16.     $tpl->pparse("output", "booklist");
  17. } else {
  18.     $tpl->setFile("nobooks", "nobooks.tpl")
  19.     $tpl->pparse("output", "nobooks");
  20. }

Это может соответствовать следующему файлу шаблона:

  1. <!-- booklist.tpl -->
  2. <table>
  3.     <tr>
  4.         <th>Author</th>
  5.         <th>Title</th>
  6.     </tr>
  7.     {books}
  8. </table>
  9.  
  10. <!-- eachbook.tpl -->
  11.     <tr>
  12.         <td>{author}</td>
  13.         <td>{title}</td>
  14.     </tr>
  15.  
  16. <!-- nobooks.tpl -->
  17. <p>Нет книг для отображения.</p>

Шаблонизаторы с использованием Zend_View_Interface

Некоторые считают более удобным использовать совместимый с Zend_View шаблонизатор. Zend_View_Interface предоставляет минимально необходимый для совместимости интерфейс:

  1. /**
  2. * Возвращает объект используемого шаблонизатора
  3. */
  4. public function getEngine();
  5.  
  6. /**
  7. * Устанавливает путь к шаблонам или скриптам вида
  8. */
  9. public function setScriptPath($path);
  10.  
  11. /**
  12. * Устанавливает базовый путь ко всем необходимым скрипту вида ресурсам
  13. */
  14. public function setBasePath($path, $prefix = 'Zend_View');
  15.  
  16. /**
  17. * Устанавливает дополнительный базовый путь к необходимым скрипту вида ресурсам
  18. */
  19. public function addBasePath($path, $prefix = 'Zend_View');
  20.  
  21. /**
  22. * Возвращает текущие пути к скриптам
  23. */
  24. public function getScriptPaths();
  25.  
  26. /**
  27. * Переопределение методов для присвоения значений переменным шаблонов как
  28. * свойствам объекта
  29. */
  30. public function __set($key, $value);
  31. public function __get($key);
  32. public function __isset($key);
  33. public function __unset($key);
  34.  
  35. /**
  36. * "Ручная" установка значения переменной шаблона или одновременное присвоение
  37. * значений нескольким переменным
  38. */
  39. public function assign($spec, $value = null);
  40.  
  41. /**
  42. * Удаление всех переменных шаблона
  43. */
  44. public function clearVars();
  45.  
  46. /**
  47. * Вывод шаблона с именем $name
  48. */
  49. public function render($name);

Используя этот интерфейс, относительно легко сделать "обертку" для шаблонизаторов сторонних разработчиков. В примере показан вариант "обертки" для Smarty:

  1. class Zend_View_Smarty implements Zend_View_Interface
  2. {
  3.     /**
  4.      * Объект Smarty
  5.      * @var Smarty
  6.      */
  7.     protected $_smarty;
  8.  
  9.     /**
  10.      * Конструктор
  11.      *
  12.      * @param string $tmplPath
  13.      * @param array $extraParams
  14.      * @return void
  15.      */
  16.     public function __construct($tmplPath = null, $extraParams = array())
  17.     {
  18.         $this->_smarty = new Smarty;
  19.  
  20.         if (null !== $tmplPath) {
  21.             $this->setScriptPath($tmplPath);
  22.         }
  23.  
  24.         foreach ($extraParams as $key => $value) {
  25.             $this->_smarty->$key = $value;
  26.         }
  27.     }
  28.  
  29.     /**
  30.      * Возвращение объекта шаблонизатора
  31.      *
  32.      * @return Smarty
  33.      */
  34.     public function getEngine()
  35.     {
  36.         return $this->_smarty;
  37.     }
  38.  
  39.     /**
  40.      * Установка пути к шаблонам
  41.      *
  42.      * @param string $path Директория, устанавливаемая как путь к шаблонам
  43.      * @return void
  44.      */
  45.     public function setScriptPath($path)
  46.     {
  47.         if (is_readable($path)) {
  48.             $this->_smarty->template_dir = $path;
  49.             return;
  50.         }
  51.  
  52.         throw new Exception('Invalid path provided');
  53.     }
  54.  
  55.     /**
  56.      * Извлечение текущего пути к шаблонам
  57.      *
  58.      * @return string
  59.      */
  60.     public function getScriptPaths()
  61.     {
  62.         return array($this->_smarty->template_dir);
  63.     }
  64.  
  65.     /**
  66.      * Метод-"псевдоним" для setScriptPath
  67.      *
  68.      * @param string $path
  69.      * @param string $prefix Не используется
  70.      * @return void
  71.      */
  72.     public function setBasePath($path, $prefix = 'Zend_View')
  73.     {
  74.         return $this->setScriptPath($path);
  75.     }
  76.  
  77.     /**
  78.      * Метод-"псевдоним" для setScriptPath
  79.      *
  80.      * @param string $path
  81.      * @param string $prefix Не используется
  82.      * @return void
  83.      */
  84.     public function addBasePath($path, $prefix = 'Zend_View')
  85.     {
  86.         return $this->setScriptPath($path);
  87.     }
  88.  
  89.     /**
  90.      * Присвоение значения переменной шаблона
  91.      *
  92.      * @param string $key Имя переменной
  93.      * @param mixed $val Значение переменной
  94.      * @return void
  95.      */
  96.     public function __set($key, $val)
  97.     {
  98.         $this->_smarty->assign($key, $val);
  99.     }
  100.  
  101.     /**
  102.      * Получение значения переменной
  103.      *
  104.      * @param string $key Имя переменной
  105.      * @return mixed Значение переменной
  106.      */
  107.     public function __get($key)
  108.     {
  109.         return $this->_smarty->get_template_vars($key);
  110.     }
  111.  
  112.     /**
  113.      * Позволяет проверять переменные через empty() и isset()
  114.      *
  115.      * @param string $key
  116.      * @return boolean
  117.      */
  118.     public function __isset($key)
  119.     {
  120.         return (null !== $this->_smarty->get_template_vars($key));
  121.     }
  122.  
  123.     /**
  124.      * Позволяет удалять свойства объекта через unset()
  125.      *
  126.      * @param string $key
  127.      * @return void
  128.      */
  129.     public function __unset($key)
  130.     {
  131.         $this->_smarty->clear_assign($key);
  132.     }
  133.  
  134.     /**
  135.      * Присвоение переменных шаблону
  136.      *
  137.      * Позволяет установить значение к определенному ключу или передать массив
  138.      * пар ключ => значение
  139.      *
  140.      * @see __set()
  141.      * @param string|array $spec Ключ или массив пар ключ => значение
  142.      * @param mixed $value (необязательный) Если присваивается значение одной
  143.      * переменной, то через него передается значение переменной
  144.      * @return void
  145.      */
  146.     public function assign($spec, $value = null)
  147.     {
  148.         if (is_array($spec)) {
  149.             $this->_smarty->assign($spec);
  150.             return;
  151.         }
  152.  
  153.         $this->_smarty->assign($spec, $value);
  154.     }
  155.  
  156.     /**
  157.      * Удаление всех переменных
  158.      *
  159.      * @return void
  160.      */
  161.     public function clearVars()
  162.     {
  163.         $this->_smarty->clear_all_assign();
  164.     }
  165.  
  166.     /**
  167.      * Обрабатывает шаблон и возвращает вывод
  168.      *
  169.      * @param string $name Шаблон для обработки
  170.      * @return string Вывод
  171.      */
  172.     public function render($name)
  173.     {
  174.         return $this->_smarty->fetch($name);
  175.     }
  176. }

В этом примере вы можете инстанцировать класс Zend_View_Smarty вместо Zend_View и использовать его так же, как используется Zend_View.

  1. //Пример 1. В initView() инициализатора
  2. $view = new Zend_View_Smarty('/path/to/templates');
  3. $viewRenderer =
  4.     new Zend_Controller_Action_HelperBroker::getStaticHelper('ViewRenderer');
  5. $viewRenderer->setView($view)
  6.              ->setViewBasePathSpec($view->_smarty->template_dir)
  7.              ->setViewScriptPathSpec(':controller/:action.:suffix')
  8.              ->setViewScriptPathNoControllerSpec(':action.:suffix')
  9.              ->setViewSuffix('tpl');
  10.  
  11. //Пример 2. Использование в контроллере действии остается тем же
  12. class FooController extends Zend_Controller_Action
  13. {
  14.     public function barAction()
  15.     {
  16.         $this->view->book   = 'Zend PHP 5 Certification Study Guide';
  17.         $this->view->author = 'Davey Shafik and Ben Ramsey'
  18.     }
  19. }
  20.  
  21. //Пример 3. Инициализация вида в контроллере действий
  22. class FooController extends Zend_Controller_Action
  23. {
  24.     public function init()
  25.     {
  26.         $this->view   = new Zend_View_Smarty('/path/to/templates');
  27.         $viewRenderer = $this->_helper->getHelper('viewRenderer');
  28.         $viewRenderer->setView($this->view)
  29.                      ->setViewBasePathSpec($view->_smarty->template_dir)
  30.                      ->setViewScriptPathSpec(':controller/:action.:suffix')
  31.                      ->setViewScriptPathNoControllerSpec(':action.:suffix')
  32.                      ->setViewSuffix('tpl');
  33.     }
  34. }

Скрипты контроллеров