Pull to refresh

Smarty в управляемой представлениями модели

Reading time4 min
Views2.8K
Обычно шаблонизатор Smarty применяется так: вы пишете код, который создаёт набор данных для шаблона, отдаёте вместе с названием шаблона смарти и тот «соединяет бренды», выводя в браузер результат.

Это так называемая модель с ведущими контроллерами. То есть контроллер полностью отвечает за то, что получил шаблонизатор и вообще командует всем.

Ещё есть модель с ведущими представлениями. В ней представление говорит контроллеру «а дай-ка мне, дорогой друг, список последних постов», после чего контроллер дёргает модель, добывает этот список, обрабатывает и отдаёт представлению (в нашем случае — шаблонизатору).

Никакая из этих моделей не является лучшей, в разных случаях удобно использовать то одно, то другое. Тем не менее, смарти-из-коробки умеет работать только по первой схеме. Обучить его работать ещё и по второй оказалось совсем несложно.

  1. <?php
  2. /**
  3. * index.php
  4. *
  5. * View-driven smarty usage sample
  6. *
  7. * Use {data id="SOMEID" var="TPLVAR"} construction in template
  8. * to fetch data for template. Return of the DataFetcher object
  9. * will be assigned to the variable with TPLVAR name.
  10. *
  11. * DataFetcher object must have function called fetch() with only
  12. * parameter which value will be SOMEID.
  13. *
  14. * Smarty included in this archieve only for your convenience.
  15. *
  16. * Remember: it's just a sample
  17. *
  18. * @copyright (c) Gregory Sitnin, 2009. All rights reserved.
  19. * @author Gregory Sitnin <gregor@gregor.ru>
  20. *
  21. */
  22.  
  23. $config['base'] = dirname(__FILE__);
  24. $config['tmp'] = $config['base'].'/tmp';
  25.  
  26. final class DataFetcher extends ConfiguratedObject {
  27.   function fetch($name) {
  28.     return 'Hello, World!';
  29.   }
  30. }
  31.  
  32. final class SmartyRender extends ConfiguratedObject {
  33.   private $smarty;
  34.   
  35.   function __construct($config) {
  36.     parent::__construct($config);
  37.     require_once $this->config['base'].'/smarty/Smarty.class.php';
  38.     $this->smarty = new Smarty();
  39.     $this->smarty->template_dir = $this->config['base'];
  40.     $this->smarty->compile_dir = $this->config['tmp'];
  41.     $this->smarty->register_function('data', array ($this, 'getDataProxy'));
  42.   }
  43.   
  44.   public function getDataProxy($params, &$smarty) {
  45.     if (!isset($params['id'])) {
  46.       $smarty->trigger_error("data: id parameter must be set.");
  47.     } elseif (!isset($params['var'])) {
  48.       $smarty->trigger_error("data: var parameter must be set.");
  49.     } else {
  50.       try {
  51.         $fetcher = new DataFetcher($this->config);
  52.         $smarty->assign($params['var'], $fetcher->fetch($params['id']));
  53.       } catch (Exception $e) {
  54.         $smarty->trigger_error('data: ('.$e->getCode().')'.$e->getMessage());
  55.       }
  56.     }
  57.   }
  58.   
  59.   function render($template, array $vars = null) {
  60.     $this->smarty->assign($vars);
  61.     return $this->smarty->fetch($template);
  62.   }
  63. }
  64.  
  65. final class App extends ConfiguratedObject {
  66.   function run() {
  67.     $render = new SmartyRender($this->config);
  68.     echo $render->render('index.tpl');
  69.   }
  70. }
  71.  
  72. abstract class ConfiguratedObject {
  73.   protected $config;
  74.   
  75.   function __construct($config) {
  76.     $this->config = $config;
  77.   }
  78. }
  79.  
  80. $app = new App($config);
  81. $app->run();
  82.  
  83. ?>
* This source code was highlighted with Source Code Highlighter.

Интересное происходит на строках 41-57. Воспользовавшись методом $smarty->register_function() я объявил новую функцию шаблона «data». Когда эта конструкция встречается в шаблоне, происходит вызов метода $this->getDataProxy() объекта SmartyRender.

На вход метода попадает ссылка на массив параметров, заданных в шаблоне и ссылка на объект smarty, который оперирует шаблоном, вызвавшим смарти-функцию.

Как здесь, так и далее нет никакой магии. Мы проверяем параметры и, если с ними всё в порядке, то создаём экземпляр класса DataFetcher. Результат вызова метода fetch() объекта DataFetcher станет переменной шаблона, которую далее можно использовать как угодно.

Сам шаблон в моём случае выглядит вот так:

  1. <html>
  2. <head>
  3.   <title>View-driven Smarty test</title>
  4. </head>
  5. <body>
  6.   {data id="test" var="test"}
  7.   Fetched: {$test}
  8. </body>
  9. </html>
* This source code was highlighted with Source Code Highlighter.

Работающий код этого примера (включает Smarty): http://gregor.ru/files/blog/vdsmarty.zip
Tags:
Hubs:
+11
Comments113

Articles

Change theme settings