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

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

профессионал

  • не нужно так много кода, как обертки потока

против

  • не так много возможностей, как с потоковыми упаковщиками (кеширование?)
  • безопасность?
  • скорость?

Вопрос

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

2 ответа

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

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

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

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

Другие вопросы по тегам