Как расширить переменные в строке

проблема

Я хотел бы расширять переменные в строке таким же образом, что и переменная в двойной кавычки расширяется.

$string = '<p>It took $replace s</>'; $replace = 40; expression_i_look_for; 

$string должно стать '<p>It took 40 s</>';

Я вижу очевидное решение, подобное этому:

 $string = str_replace('"', '\"', $string); eval('$string = "$string";'); 

Но мне это действительно не нравится, потому что eval () небезопасен. Есть ли другой способ сделать это?

контекст

Я строю простой шаблонный движок, вот где мне это нужно.

Шаблон примера (view_file.php)

 <h1>$title</h1> <p>$content</p> 

Редактирование шаблона (упрощенный код):

 $params = array('title' => ...); function render($view_file, $params) extract($params) ob_start(); include($view_file); $text = ob_get_contents(); ob_end_clean(); expression_i_look_for; // this will expand the variables in the template return $text; } 

Расширение переменных в шаблоне упрощает его синтаксис. Без него приведенный выше примерный шаблон:

 <h1><?php echo $title;?></h1> <p><?php echo $content;?></p> 

Считаете ли вы, что этот подход хорош? Или я должен смотреть в другом направлении?

редактировать

Наконец, я понимаю, что нет простого решения из-за гибкого способа PHP расширяет переменные (даже ${$var}->member[0] будет действительным.

Таким образом, существует только два варианта:

  1. Принять существующую полноценную систему шаблонов
  2. Придерживайтесь чего-то очень простого, которое по существу ограничено включением файлов вида через include .

Я бы предпочел использовать некоторые существующие механизмы шаблонов, такие как, например, Smarty, но если вы действительно хотите сделать это самостоятельно, вы можете использовать простое регулярное выражение для соответствия всем переменным, построенным с помощью, например, букв и цифр, а затем заменить их на правильные переменные :

 <?php $text = 'hello $world, what is the $matter? I like $world!'; preg_match_all('/\$([a-zA-Z0-9]+)/', $text, $out, PREG_PATTERN_ORDER); $world = 'World'; $matter = 'matter'; foreach(array_unique($out[1]) as $variable){ $text=str_replace('$'.$variable, $$variable, $text); } echo $text; ?> 

печать

Привет, мир, в чем дело? Мне нравится мир!

Вы хотите что-то подобное?

 $replace = 40; $string = '<p>It took {$replace}s</p>'; 

парсить

Разберите строку \[a-zA-Z_\x7f-\xff\]\[a-zA-Z0-9_\x7f-\xff\]* $ за которой следует действительное имя переменной (т. \[a-zA-Z_\x7f-\xff\]\[a-zA-Z0-9_\x7f-\xff\]* )

Variable²

Используйте синтаксис переменных переменных (т. $$var Обозначение $$var ).

Вместо использования одинарных кавычек

 $string = '<p>It took $replace s</>'; $replace = 40; 

использовать двойные кавычки

 $replace = 40; $string = "<p>It took $replace s</>"; 

Однако для удобства чтения и для того, чтобы вы могли удалить пробел между $ replace и s, я бы использовал:

 $replace = 40; string = '<p>It took ' . $replace . 's</>'; 

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

Это более сложное решение, но значительно упростится, когда вы поймете, что хотите иметь возможность отображать списки, длина которых неизвестна заранее, используя какую-то петлевую структуру на основе стандартной опции отображения. В конечном счете, вы не найдете много серьезных систем шаблонов, которые не анализируют документы в виде какого-либо дерева в памяти, где могут быть вставлены заполнители, а затем документ создан по мере необходимости. Это также предоставляет множество возможностей для кэширования. Кроме того, если вы не боитесь рекурсии, вы сможете выполнять множество операций на нем довольно просто.

Однако это не редко встречающаяся проблема, и когда я прокомментировал этот вопрос, почти наверняка будут библиотеки и расширения, которые обеспечивают большую часть необходимых вам функций. Если это не чисто академический процесс для вас, я бы нашел некоторые существующие решения и либо использовал один из них, либо получил четкое представление о том, как он работает, поэтому у вас есть отправная точка для адаптации вашего собственного решения.

Вы пытаетесь это сделать?

templater.php:

 <?php $first = "first"; $second = "second"; $third = "third"; include('template.php'); 

template.php:

 <?php echo 'The '.$first.', '.$second.', and '.$third.' variables in a string!'; 

Когда templater.php запущен, производится:

 "The first, second, and third variables in a string!" 

Это фрагмент, который я вытащил из ответа Лейсло. Я тестировал его, и он отлично работает.

 function resolve_vars_in_str( $input ) { preg_match_all('/\$([a-zA-Z0-9]+)/', $input, $out, PREG_PATTERN_ORDER); foreach(array_unique($out[1]) as $variable) $input=str_replace('$'.$variable, $GLOBALS["$variable"], $input); return $input ; }