Свой шаблонизатор

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

Обределимся с минимумом:

  1. Передать переменную в шаблонизатор
  2. Взять переменную из шаблонизатора
  3. Отобразить шаблон

Тем самым мы получили наш интерфейс. В кодинге будем придерживаться стандартов хорошо зарекомендовавших себя ещё во времена PEAR.
файл Amdy/Templater/Interface.php

<?php
interface Amdy_Templater_Interface {
    public function __set($key, $value);
    public function __get($key);
    public function display($tpl);
?>

Применяем магические меоды __set и __get для присвоения значения переменной и для её последующей экзекуции. display для вывода содержимого шаблона с нужными вставками.

Сейчас начнём реализаци. Создаём абстрактный класс и пишем код

файл Amdy/Templater/Abstract.php

<?php
require_once('Amdy/Templater/Interface.php');
abstract class Amdy_Template_Abstract implements Amdy_Templater_Interface {
    protected $_data = array();
    public function __set($key, $value) {
        $this->_data[$key] = $value;
    }
    public function __get($key) {
        return isset($this->_data[$key]) ? $this->_data[$key] : null;
    }
    public function display($tpl) {
        require($tpl);
    }
}
?>

Защищённая переменная $_data нужна нам для слаживания наших переменных шаблона. Соответственно чтобы присвоить, достаточно сделать вызов

$tpl->имя_переменной = значение

для вывода

echo $tpl->имя_переменной

Ну а display вызовет наш шаблон, который будет выполнен в своеобразном неймспайсе шаблонизатора, соответственно будут недоступны глобальные переменные, зато будет доступ к $this.

Что ж теперь займёмся созданием непосредственно класса Templater

файл Amdy/Templater.php

<?php
require_once('Amdy/Templater/Abstract.php');
class Amdy_Templater extends Amdy_Template_Abstract {

}
?>

Упс. Нам ничего не нужно реализовывать, так как всё уже сделано в абстрактном классе. А вот в следующий раз, когда у меня дойдут руки, позанимаемся переопределением методов и нарастим шаблонизатор. К тому времени я постараюсь таки установить плагин для слинковывания статей.

Нарисуем шаблон для вывода

файл test.tpl.php

teplater !<?=$this->test?>! teplater

Между двумя восклицательными знаками должно появиться значение переменной шаблона test. Как видите, я использовал короткие теги, что как бы не рекомендуется, но я ещё не встречал хостинга, где бы были запрещены короткие теги, а программист человек ленивый и культурный, потому старается не писать лишний раз где попало три заветные буковки. Так же короткая нотация echo, тоже из лени, да и наглядности добавляет.

Ну и перемешаем все ингредиенты дабы получить приготовляемое блюдо.

файл index.php

<?php
require_once('Amdy/Templater.php');
$tpl = new Amdy_Templater();
$tpl->test = 'test';
$tpl->display('test.tpl.php');
?>

На всякий случай привожу структуру каталога.

Свой шаблонизатор: 10 комментариев

  1. AmdY Автор записи

    Согласен, сдутый view. хм, а helper тоже можно реализовать, только я планирую снача развить сам класс, при этом показывая на фичи ООП. А полноценный шаблонизатор делать не хочется, я противник php шаблонов.

  2. kelvin

    скажите, зачем здесь интерфейс, если можно было оьойтись без него?
    в чем его смысл?

    1. admin Автор записи

      интерфейс действительно не является таким уж необходимым, но даёт ряд преимуществ. например, вы решите заменить данных шаблонизатор на smarty. чтобы не переписывать весь php код, нужно просто создать новый класс, наследующий smarty и удовлетворяющий интерфейсу. это значит, что в новом классе должны обязательно присутствовать методы
      public function __set($key, $value);
      public function __get($key);
      public function display($tpl);
      например для smarty метод __set
      public function __set($key, $value) {
      return $this->assign($key, $value);
      }

      1. kelvin

        ну в таком случае нам так же не обязателен интерфейс. разве чтоб сторонние разработчики при смене шаблонизатора не забыли сделать всё так, как надо

        1. admin Автор записи

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

  3. Николай

    Интересная тема, продолжайте. Иногда нахожу ответы, которые получить самому просто реально не хватает времени. Спасибо вам огромное!

  4. Morgan

    Зачем в данном случае интерфейс, если есть абстрактный класс ?
    Раз абстрактный — не поддается изменению, и интерфейс вообще следует выпилить

    1. AmdY Автор записи

      абстрактный класс реализует логику, а интерфейс — требования. Пост демонстрирует как пользоваться ООП возможностями php, поэтому нельзя без очереди интерфейс, абстрактный класс, конкретная реализация. Вообще построение архитектуры приложения у меня начинается с описания интерфейса, правда не с ООП версией interface …., а вроде как при разработке через тестирование: сразу пишу код, который должен работать, а затем уже сам код классов.
      p.s. А интерфейс я действительно затем выбрасываю. точно так же как и большинство абстрактных классов, не люблю избыточность, если у меня будет всего одна реализация, то фтопку abstract & interface.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *