Как смоделировать шаблонный класс - PullRequest
0 голосов
/ 17 января 2010

Я пишу базовый шаблонный класс для своего собственного проекта. Основное использование это:

$template = new Template('template_file.php');
$template->assignVariable('pageTitle', 'Home page');
$template->render();

Содержимое файла template_file.php:

<?php print $pageTitle; ?>

Вот что шаблонный класс делает шаг за шагом:

  1. Хранит переменные в приватном массиве при вызове метода assignVariable
  2. При вызове метода рендеринга извлекает сохраненные переменные, включает файл шаблона в блоке ob_start() и ob_end_clean(). Сохраняет вывод в переменной с ob_get_contents(), а затем печатает сохраненный вывод.

Я знаю, что это очень простой шаблонный класс, но работает как положено. Вопрос в том, должен ли я делегировать включаемый файл шаблона другому классу? У меня был этот вопрос, когда я писал модульные тесты для этого класса. Я думал, что взаимодействие с файловой системой должно быть инкапсулировано. Как вы думаете? Если вы думаете, что это не должно, как я могу высмеивать включение файла в мои тесты?

Может быть, я просто передаю содержимое файла шаблона классу так:

$templateContent = file_get_contents('template_file.php');
$template = new Template($templateContent);
...

Редактировать: я решил инкапсулировать процесс ввода класса шаблона для написания лучших модульных тестов и инкапсуляции. Но, как отметил Йоханнес, мне нужно было использовать eval() для этой цели, которая казалась неправильной. Йоханнес указал мне на направление потоковых упаковщиков для насмешек над включением в модульные тесты. Но это вдохновило меня на новую идею. Вот что я собираюсь сделать; Я буду продолжать использовать include() в своем классе шаблонов, но на этот раз с обертками потока. Я передам обработчик протокола моему шаблонному классу при его инициализации. Таким образом, я могу создать свои собственные потоковые обертки для извлечения данных шаблона из базы данных или использования локальной переменной. Вот примеры:

$template = new Template('file://template_file.php');

stream_wrapper_register('database', 'My_Database_Stream');
$template = new Template('database://templates/3'); // templates table, row id 3

stream_wrapper_register('var', 'My_Var_Stream');
$myTemplate = '<?php print "Hello world!"; ?>';
$template = new Template('var://myTemplate');

Я уже реализовал пользовательскую потоковую оболочку для локальных переменных. Вот оно:

class My_Var
{
    protected $position;
    protected $variable;
    function stream_open($path, $mode, $options, &$openedPath) {
        $url = parse_url($path);
        global $$url['host'];
        $this->variable = $$url['host'];
        $this->position = 0;

        return true;
    }
    public function stream_read($count) {
        $ret = substr($this->variable, $this->position, $count);
        $this->position = strlen($ret);
        return $ret;
    }
    public function stream_eof() {
        return $this->position >= strlen($this->variable);
    }
}


stream_wrapper_register('var', 'My_Var');
$myvar = '<?php print "mert"; ?>';
include 'var://myvar';
exit;

Ответы [ 4 ]

1 голос
/ 17 января 2010

Мне всегда нравился подход этого парня:

http://www.massassi.com/php/articles/template_engines/

Этот подход использует тот факт, что PHP был запущен как шаблонизатор. (Автор также отмечает, что глупо писать раздутый шаблонизатор на PHP, хотя на самом деле он сам является шаблонизатором.) На самом деле он может не отвечать непосредственно на ваш вопрос, но, возможно, он вам поможет.

0 голосов
/ 17 января 2010

Независимо от зла ​​eval против использования include, чтобы ответить на ваш вопрос, мне придется согласиться и использовать отдельный класс для инкапсуляции аспекта ввода-вывода вашего решения.

Хотя это может показаться излишним (как это будет происходить в большинстве случаев), это, вероятно, единственный разумный способ обеспечить изоляцию внедрения управления / зависимости, к которой вы стремитесь.

0 голосов
/ 17 января 2010

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

Вопрос, а почему бы и нет?

0 голосов
/ 17 января 2010

Передавая содержимое с помощью file_get_contents () и тому подобного, вы должны использовать eval () для выполнения, что плохо во многих отношениях. Одним из наиболее важных здесь является то, что кэш кода операции не может кэшировать файл тогда. Выполнение включения ('template_file.php'); давайте APC или другие кешируем скомпилированный скрипт.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...