Как написать простейший шаблонизатор на регулярных выражениях для замены конструкций типа {{ var }} и {if (condition)} на валидный PHP-код?
Создание простейшего шаблонизатора на регулярных выражениях — отличный способ понять, как работают популярные движки вроде Blade или Twig. Рассмотрим реализацию шаг за шагом.
## Основная идея
Шаблонизатор принимает строку с шаблоном, находит специальные конструкции с помощью `preg_replace` или `preg_replace_callback` и заменяет их валидным PHP-кодом, который затем выполняется через `eval()` или сохраняется во временный файл и подключается через `include`.
## Шаг 1. Замена переменных {{ var }}
Конструкция `{{ var }}` должна превращаться в «.
php
function compileVariables(string $template): string {
return preg_replace(
‘/{{s*(w+)s*}}/’,
»,
$template
);
}
Регулярное выражение `{{s*(w+)s*}}` ищет двойные фигурные скобки с именем переменной внутри. `s*` допускает пробелы вокруг имени.
## Шаг 2. Замена условий {if (condition)}
Конструкция `{if (condition)}` превращается в «.
php
function compileIf(string $template): string {
$template = preg_replace(
‘/{ifs*((.+?))}/’,
»,
$template
);
$template = preg_replace(
‘/{/if}/’,
»,
$template
);
return $template;
}
## Шаг 3. Циклы {foreach ($arr as $item)}
php
function compileForEach(string $template): string {
$template = preg_replace(
‘/{foreachs*((.+?))}/’,
»,
$template
);
$template = preg_replace(
‘/{/foreach}/’,
»,
$template
);
return $template;
}
## Шаг 4. Компиляция и рендеринг
php
function render(string $templatePath, array $vars = []): string {
$template = file_get_contents($templatePath);
$template = compileVariables($template);
$template = compileIf($template);
$template = compileForEach($template);
$tmpFile = sys_get_temp_dir() . ‘/’ . md5($templatePath) . ‘.php’;
file_put_contents($tmpFile, $template);
extract($vars);
ob_start();
include $tmpFile;
return ob_get_clean();
}
## Шаг 5. Пример использования
Шаблон `hello.tpl`:
Привет, {{ name }}!
{if ($age >= 18)}
Вы совершеннолетний.
{/if}
Вызов:
php
echo render(‘hello.tpl’, [‘name’ => ‘Иван’, ‘age’ => 25]);
## Важные замечания
— **Безопасность**: всегда экранируйте вывод переменных через `htmlspecialchars`, чтобы избежать XSS.
— **Кэширование**: сохраняйте скомпилированные файлы и проверяйте дату изменения исходника, чтобы не компилировать шаблон при каждом запросе.
— **Вложенные конструкции**: простые регулярные выражения плохо справляются с глубокой вложенностью — для сложных случаев используйте рекурсивные паттерны или парсер.
Такой шаблонизатор подходит для учебных проектов и небольших утилит, когда подключение Twig или Blade избыточно.
