Пользовательская потоковая оболочка с 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().

Pro

  • Мне не нужно менять код

Contra

  • При возникновении ошибки в шаблоне вы получаете только бесполезное сообщение об ошибке, которое не  сообщите вам, в каком файле произошла ошибка, и иногда номер строки даже ошибочен.
  • Безопасность? Файлы шаблонов нужны только для чтения?
  • Сложно отлаживать код.
  • Код сложнее понять
  • больше..?

обтекатели потоков и include()

Недавно я прочитал об обтекателях потока в php. Вы даже можете создать свой собственный. Другим решением, чем eval, было бы создание персонализированной обертки потока для каждого формата шаблона и использование include для анализа шаблона.

Это имеет следующие (потенциальные) недостатки:

Pro

  • может решить проблемы с отображением неправильного файла/номера строки в сообщениях об ошибках (есть ли у кого-нибудь опыт?)
  • вы можете обрабатывать файл шаблона именно так, как его нужно обрабатывать. Полный контроль.

Contra

  • allow_url_(fopen|include) должен быть включен?
  • Это медленно? (и eval() слишком медленный?)
  • нет безопасности. включить в основном то же самое, что и eval.
  • больше...?

EDIT: кэшированные проанализированные файлы и включают()

Третий вариант должен был бы проанализировать шаблон на PHP-код и кэшировать его (как это предложил @Jen-YaKovalev).

Pro

  • включает кеширование

Contra

  • если возникает ошибка при включении созданного шаблона и возникает ошибка  сообщение об ошибке не указывает вам на правильный файл/в конечном итоге показывает вам  неправильный номер строки.
  • Для сохранения проанализированных файлов вам понадобится дополнительный tmp/ каталог. Вам нужно написать  разрешения для PHP/webserver. Было бы более неуверенно, поскольку хакеры  добавит некоторый вредоносный код.

ИЗМЕНИТЬ: фильтры потока и включите ('php://filter')

в последнее время нашли следующие страницы php.net:

Это была бы другая возможность решить эту проблему. Используя include('php://filter/read=filtername/resource=file.php'), я мог бы включить файл, который сначала будет проходить через фильтр filtername, прежде чем он будет выполнен.

Pro

  • не требуется столько кода, как обтекатели потоков

Contra

  • Не так много возможностей, как с обтекателями потоков (кэширование?)
  • безопасность?
  • скорость?

Вопрос

  • У вас есть опыт использования обтекателей потоков для анализа файлов шаблонов или подобных?
  • Есть ли еще какое-то другое решение?
  • Есть ли больше pro и contras?
  • Какой из них вы бы порекомендовали?

Ответ 1

Я думаю, что это просто вкус одного стиля кодирования, вам лучше проголосовать за него или что-то в этом роде.

  • Я лично думаю, что eval - зло (на каждом языке),
  • имел плохие впечатления от включения + php-обертки (даже интегрированные *),
  • зная, что все большие (gish) шаблонные системы используют компиляцию в php файле (smarty, twig), это тот, который я бы использовал.

(*) В более раннем проекте мы использовали 1-строчный код (пустое расширение класса) в data-url, который включает, и его производительность была ужасной.

Ответ 2

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