Я пытаюсь создать базовый шаблонный движок. Подобно механизмам шаблонов, которые уже доступны как с открытым исходным кодом, я использую методы поиска и замены.
Однако, поскольку поиск и замена должны быть жестко закодированы, это не так много гибкости. Я хочу сказать, что в качестве примера я использую что-то вроде этого
$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.
Регулярное выражение, которое вы ищете, это {_(\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;