Обновление - Спасибо за все ответы. Этот вопрос становится немного грязным, поэтому я начал продолжение , если кому-то интересно.
Я составлял быстрый скрипт для друга и наткнулся на очень простой способ создания шаблонов в PHP.
По сути, идея состоит в том, чтобы разобрать html-документ как строку heredoc, поэтому переменные внутри него будут расширяться PHP.
Сквозная функция позволяет выполнять оценку выражений, а также вызовы функций и статических методов внутри строки:
function passthrough($s){return $s;}
$_="passthrough";
Код для разбора документа внутри строки heredoc смехотворно прост:
$t=file_get_contents('my_template.html');
eval("\$r=<<<_END_OF_FILE_\n$t\_END_OF_FILE_;\n");
echo $r;
Единственная проблема в том, что он использует eval
.
Вопросы
Может кто-нибудь придумать, как создать шаблон такого рода без использования eval
, но без добавления анализатора или тонны безумия регулярных выражений?
Есть предложения по обходу случайных знаков доллара, которые не принадлежат переменным PHP, без написания полноценного парсера? Делает ли проблема со случайным знаком доллара, что этот подход не подходит для «серьезного» использования?
Вот пример шаблонного HTML-кода.
<script>var _lang = {$_(json_encode($lang))};</script>
<script src='/blah.js'></script>
<link href='/blah.css' type='text/css' rel='stylesheet'>
<form class="inquiry" method="post" action="process.php" onsubmit="return validate(this)">
<div class="filter">
<h2>
{$lang['T_FILTER_TITLE']}
</h2>
<a href='#{$lang['T_FILTER_ALL']}' onclick='applyFilter();'>
{$lang['T_FILTER_ALL']}
</a>
{$filter_html}
</div>
<table class="inventory" id="inventory_table">
{$table_rows}
<tr class="static"><th colspan="{$_($cols+1)}">
{$lang['T_FORM_HELP']}
</th></tr>
{$form_fields}
<tr class="static">
<td id="validation" class="send" colspan="{$cols}"> </td>
<td colspan="1" class="send"><input type="submit" value="{$lang['T_SEND']}" /></td>
</tr>
</table>
</form>
Зачем использовать шаблоны?
Было некоторое обсуждение того, нужно ли создавать шаблонный слой в PHP, который, по общему признанию, уже довольно хорош в шаблонизации.
Несколько быстрых причин, полезных для шаблонирования:
Вы можете управлять им
Если вы предварительно обработаете файл до того, как он поступит в интерпретатор, у вас будет больше контроля над ним. Вы можете вводить вещи, блокировать разрешения, очищать от вредоносного php / javascript, кэшировать его, запускать через xsl-шаблон, что угодно.
Хороший дизайн MVC
Шаблонирование способствует разделению вида от модели и контроллера.
При поиске и выводе тегов <?php ?>
в вашем представлении легко лениться и выполнять некоторые запросы к базе данных или выполнять другие действия на сервере. При использовании метода, подобного описанному выше, только один оператор может быть использован для каждого «блока» (без точек с запятой), поэтому гораздо труднее попасть в эту ловушку. <?= ... ?>
имеют почти такое же преимущество, но ...
Короткие теги не всегда включены
... и мы хотим, чтобы наше приложение работало в различных конфигурациях.
Когда я первоначально собираю концепцию вместе, она начинается как один файл php. Но прежде чем он вырастет, я не буду счастлив, если у всех php-файлов нет только одного <?php
в начале и одного ?>
в конце, и желательно, чтобы все были классами, за исключением таких вещей, как контроллер, настройки, сервер изображений и т. Д.
Мне вообще не нужно много PHP в моих взглядах, потому что дизайнеры запутываются, когда Dreamweaver или что-то еще кашляет кровать, когда он видит что-то вроде этого:
<a href="<?php $img="$img_server/$row['pic'].png"; echo $img; ?>">
<img src="<?php echo $img; ?>" /></a>
Это достаточно сложно для программиста. Среднестатистический графический дизайнер никуда не денется. С чем-то вроде этого гораздо легче справиться:
<a href="{$img}"><img src="{$img}" /></a>
Программист скрыл свой неприятный код от html, и теперь дизайнер может творить свое волшебство дизайна. Ура!
Быстрое обновление
Принимая во внимание всеобщее мнение, я думаю, что предварительная обработка файлов - это путь, и промежуточные файлы должны быть как можно ближе к обычному шаблону php, с тем, чтобы шаблоны были синтаксическим сахаром. Эвал все еще на месте, пока я играю с ним. Это наследство как бы изменило свою роль. Я напишу больше позже и постараюсь ответить на некоторые ответы, но пока ...
<?php
class HereTemplate {
static $loops;
public function __construct () {
$loops=array();
}
public function passthrough ($v) { return $v; }
public function parse_markup ($markup, $no_escape=null, $vars=array()) {
extract($vars);
$eot='_EOT_'.rand(1,999999).'_EOT_';
$do='passthrough';
if (!$no_escape) $markup=preg_replace(
array(
'#{?{each.*(\$\w*).*(\$\w*).*(\$\w*).*}}?#',
'#{?{each.*(\$\w*).*(\$\w*).*}}?#',
'#{?{each}}?#',
'#{{#', '#}}#',
'#{_#', '#_}#',
),
array(
"<?php foreach (\\1 as \\2=>\\3) { ?>",
"<?php foreach (\\1 as \\2) { ?>",
"<?php } ?>",
"<?php echo <<<$eot\n{\$this->passthrough(", ")}\n$eot\n ?>",
"<?php ", " ?>",
),
$markup);
ob_start();
eval(" ?>$markup<?php ");
echo $markup;
return ob_get_clean();
}
public function parse_file ($file) {
// include $file;
return $this->parse_markup(file_get_contents($file));
}
}
// test stuff
$ht = new HereTemplate();
echo $ht->parse_file($argv[1]);
?>
...
<html>
{{each $_SERVER $key $value}
<div id="{{$key}}">
{{!print_r($value)}}
</div>
{each}}
</html>