Небольшой урок о том, как написать простой шаблонизатор на php (аналогичный тому что используется в yii).
Для удобства напишем его используя ООП и будем использовать php7. Для начала создадим каркас класса View:
class View { private $path = __DIR__ . '/templates/'; public $data = []; public function setData(array $data) : View { // } public function render(string $templateName) : string { // } }
Здесь $data будет содержать параметры которые будут переданы в шаблон. Единственный метод render() будет компилировать шаблон и возвращать готовый результат. Это позволит, например, рендерить страницу из множества модульных шаблонов:
echo (new View) ->setData([ 'cart' => (new View) ->setData([...]) ->render() ]) ->render();
Опишем реалзацию для метода setData(). Он позволит не заменять данные а сливать уже указанные данные с теми что переданы в агрументе:
public function setData(array $data) : View { $this->data = array_merge($this->data, $data); return $this; }
А теперь напишем сам метод рендера. В php для этого есть функции ob_start(), ob_get_clean() для работы с буфером. На самом деле мы будем просто запускать выполнение интерпретатора и писать результат в буфер, а затем очищать буфер и возвращать результат.
public function render(string $templateName) : string { $path = $this->path . $templateName; if (!file_exists($path)) { throw new Exception('Template file ' . $path . ' does not exists'); } extract($this->data); ob_start(); include($path); return ob_get_clean(); }
Логика работы проста: проверим существует ли файл и если он существует, то вызовем функцию extract() и скомпилируем шаблон.
На выходе у нас получается вот такой класс:
class View { private $path = __DIR__ . '/templates/'; public $data = []; public function setData(array $data) : View { $this->data = array_merge($this->data, $data); return $this; } public function render(string $templateName) : string { $path = $this->path . $templateName; if (!file_exists($path)) { throw new Exception('Template file ' . $path . ' does not exists'); } extract($this->data); ob_start(); include($path); return ob_get_clean(); } }