Я пишу базовый шаблонный класс для своего собственного проекта. Основное использование это:
$template = new Template('template_file.php');
$template->assignVariable('pageTitle', 'Home page');
$template->render();
Содержимое файла template_file.php:
<?php print $pageTitle; ?>
Вот что шаблонный класс делает шаг за шагом:
- Хранит переменные в приватном массиве при вызове метода assignVariable
- При вызове метода рендеринга извлекает сохраненные переменные, включает файл шаблона в блоке
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;