Создание простого, но гибкого шаблонного механизма

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

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

$templateMarkup = '<div class="title">{_TITLE_}</div>'; $renderedMarkup = str_replace("{_TITLE_}",$title,$templateMarkup); echo $renderedMarkup; 

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

Я немного слаб в регулярном выражении. Но я знаю, если я могу разработать регулярное выражение, которое может соответствовать всему тексту, начинающемуся с {_ и заканчивая _} и получить значение между ними, я просто смогу создать гибкий механизм шаблонов.

Мне нужна помощь в регулярном выражении.

Если я полностью пойду не так, как это сделать, пожалуйста, предупредите меня.

Для тех, кто думает, что я изобретаю колесо. Вот мое объяснение

 Templating engines, that are already available are quite unnecessarily complex. My requirements are simple and so I am builidng my own simple engine. 

Solutions Collecting From Web of "Создание простого, но гибкого шаблонного механизма"

Регулярное выражение, которое вы ищете, это {_(\w+)_} , если ваши теги шаблона – всего лишь одно слово. Вы использовали бы это примерно так:

 <?php $replacements = array( "firstname" => "John", "lastname" => "Smith" ); $template_markup = "Hello {_firstname_} {_lastname_}"; if(preg_match_all('/{_(\w+)_}/', $template_markup, $matches)) { foreach($matches[1] as $m) { $template_markup = str_replace("{_".$m."_}", $replacements[$m], $template_markup); } } echo $template_markup; ?> 

Вы увидите, что preg_match_all имеет косые черты, окружающие регулярное выражение, это разделители.

Обновление. Если вы хотите расширить регулярное выражение за пределами отдельных слов, будьте осторожны при использовании . для соответствия любому персонажу. Лучше использовать что-то подобное, чтобы указать, что вы хотите включить другие символы: {_([\w-_]+)_} . [\w-_] означает, что он будет соответствовать буквенно-цифровым символам, дефисам или символам подчеркивания.

(Возможно, кто-то может объяснить, почему использование может быть плохой идеей? Я не уверен на 100%).

Если вы не пытаетесь ограничить то, что люди могут делать в шаблоне, и хотите контролировать, какую надпись они могут вставить, я бы рекомендовал PHP в качестве красивого языка шаблонов!

Если вы хотите придерживаться своего решения, вы можете сделать что-то подобное для управления заменами.

 $template = "foo={_FOO_},bar={_BAR_},title={_TITLE_}\n"; $replacements = array( 'title' => 'This is the title', 'foo' => 'Footastic!', 'bar' => 'Barbaric!' ); function map($a) { return '{_'. strtoupper($a) .'_}';} $keys = array_map("map", array_keys($replacements)); $rendered = str_replace($keys, array_values($replacements), $template); echo $rendered; 

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

  • Благодаря Sam для части регулярного выражения
  • Спасибо James за часть str_replace() режиме массива.

Вот решение:

 $replacements = array( "firstname" => "John", "lastname" => "Smith" ); function getVal($val) { global $replacements; return $replacements[$val]; } $template_markup = "Hello {_firstname_} {_lastname_}"; preg_match_all('/{_(\w+)_}/', $template_markup, $matches); $rendered = str_replace($matches[0], array_map("getVal",array_values($matches[1])), $template_markup); echo $rendered;