2010-01-17 2 views
0

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

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

Содержание «template_file.php»:

<?php print $pageTitle; ?> 

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

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

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

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

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

Edit: я решил инкапсулировать процесс ввода класса шаблона для написания более модульных тестов и инкапсулирование. Но, как указал Йоханнес, мне нужно было использовать 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; 

ответ

0

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

+0

Да, но при использовании функции include мне нужен фиктивный файл шаблона в моей тестовой папке. Также не следует ли тестировать только класс шаблонов? Также как я буду фальсифицировать функцию include? – matte

+0

Вы можете использовать пользовательскую поточную оболочку или поставщик данных для отправки посмеиваемых данных. http://php.net/stream_wrapper_register http://php.net/manual/en/wrappers.data.php – johannes

+0

Привет, Йоханнес, спасибо! Вы вдохновили меня на меня. Я отредактировал вопрос и добавил решение, с которым я пришел. – matte

0

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

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

0

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

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

+0

может быть перебор? – matte

+0

, только если «overkill» был вашим ответом на модульные тесты. ;) –

+0

не overkill ofcourse. Я придумал решение, которое полностью инкапсулирует мой класс шаблонов. Я добавил решение к моему вопросу. – matte

1

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

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

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

+0

Мой шаблонный класс очень похож на его, на самом деле тот же. Но мой вопрос заключался в том, что я должен инкапсулировать, включая файл? Что делать, если мне нужно проанализировать текст, полученный из db? – matte

+0

Метод, описанный в приведенной выше ссылке, не находится в миллионе миль от того, как обрабатываются сценарии представления в Zend Framework. Сценарии просмотров находятся в контексте родительского объекта представления, что позволяет вам делать вызовы (которые затем проксируются для плагинов вообще) вспомогательным методам. Это полезно, если, например, вам нужно выполнить экранирование (вы можете просто выполнить escape ($ this-> var);). – berty

Смежные вопросы