Пользовательская потоковая оболочка с include или eval?
обзор
Я сейчас пишу шаблонизатор. Он даже поддерживает несколько форматов. В настоящее время это может разобрать .php
файлы и .tpl
(специфично для этого двигателя).
Я приведу небольшой пример того и другого, просто чтобы дать вам идею.
template.php:
Name: <?php echo $this->h($name) ?>
Posts:
<?php foreach($posts as $post): ?>
- <?php echo $this->h($post->name) ?> (<?php echo count($post->comments) ?> comments)
<?php echo $this->render('post/shortpost', array('post' => $post)) ?>
<?php endforeach ?>
Это в основном просто стандартный PHP.
template.tpl
Name: {>$name}
Posts:
{foreach($posts as $post):}
- {>$post->name} ({=count($post->comments)} comments)
{=:render('post/shortpost', array('post' => $post))}
{endforeach}
Этот шаблонный "язык" просто переводится на PHP выше.
Comparission
Eval()
В настоящее время эти шаблоны анализируются с использованием eval()
,
профессионал
- Мне не нужно менять код
против
- когда в шаблоне возникает ошибка, вы получаете только бесполезное сообщение об ошибке, в котором не указано, в каком файле произошла ошибка, а иногда даже номер строки неверен.
- Безопасность? Файлы шаблонов должны быть только для чтения?
- Сложно отлаживать код.
- Код сложнее понять
- Больше..?
потоковые обертки и include()
Я недавно читал о потоковых упаковщиках в php. Вы даже можете создать свой собственный. Другое решение, чем eval
было бы создать пользовательскую потоковую оболочку для каждого "формата" шаблона и использовать include для разбора шаблона.
Это имеет следующие (потенциальные) недостатки:
профессионал
- может решить проблемы с отображением неверного номера файла / строки в сообщениях об ошибках (кто-нибудь сталкивался с этим?)
- Вы можете обработать файл шаблона именно так, как хотите, чтобы он обрабатывался. Полный контроль.
против
allow_url_(fopen|include)
должен быть включен?- это медленно? (является
eval()
тоже медленно?) - нет выгоды в безопасности. include в основном делает то же самое, что и eval.
- Больше...?
РЕДАКТИРОВАТЬ: кэшированные проанализированные файлы и включить ()
Третий вариант - проанализировать шаблон в PHP-коде и кэшировать его (как предложено @Jen-YaKovalev).
профессионал
- включает в себя кеширование
против
- Если при включении отрендеренного шаблона произошла ошибка и возникла ошибка, сообщение об ошибке не указывает на правильный файл / в конечном итоге показывает неправильный номер строки.
- Вам нужен дополнительный
tmp/
каталог для сохранения проанализированных файлов. Вам нужны разрешения на запись для PHP/ веб-сервера. Было бы более небезопасно, потому что хакеры могли бы добавить некоторый вредоносный код.
РЕДАКТИРОВАТЬ: потоковые фильтры и включить ('php:// фильтр')
В последнее время найдены следующие страницы php.net:
php://filter:
http://www.php.net/manual/en/wrappers.php.phpstrea_filter_register
http://fr2.php.net/manual/en/function.stream-filter-register.php
Это была бы другая возможность решить эту проблему. С помощью include('php://filter/read=filtername/resource=file.php')
Я мог бы включить файл, который сначала прошел бы через фильтр filtername
до того, как это будет выполнено.
профессионал
- не нужно так много кода, как обертки потока
против
- не так много возможностей, как с потоковыми упаковщиками (кеширование?)
- безопасность?
- скорость?
Вопрос
- Есть ли у вас опыт использования потоковых упаковщиков для разбора файлов шаблонов или аналогичных?
- Есть ли еще другое решение?
- Есть еще плюсы и минусы?
- Какой из них вы бы порекомендовали?
2 ответа
Я думаю, что это просто вкус стиля кодирования, вам лучше проголосовать за него или что-то в этом роде.
- Я лично думаю, что Eval это зло (на каждом языке),
- имел плохой опыт работы с обертками include + php (даже встроенными *),
- зная, что все большие (gish) системы шаблонов используют компиляцию в php-файл (smarty, twig), я бы это использовал.
(*) В более раннем проекте мы использовали 1-строчный код (пустое расширение класса) в включенном URL-адресе данных, и его производительность была ужасной.
Вы, конечно, не хотите анализировать шаблоны при каждом запросе в производственной среде, это будет пустой тратой ресурсов и, следовательно, медленным и не очень разумным подходом, поэтому я настоятельно рекомендую использовать кэшированные проанализированные файлы и включать () подход.