preg_replace_callback с обычными анонимными функциями, где для доступа к $this приходится использовать конструкцию use($this).Такой код рабочий, но визуально тяжёлый и избыточный. Современный PHP (начиная с версии 7.4) позволяет сделать его чище, лаконичнее и удобнее в поддержке — за счёт стрелочных функций.
Что было раньше: Классический синтаксис
Типичный старый вариант выглядит так:
ВыделитьPHP
$text = preg_replace_callback(
'/\[url(.*?)\](.*?)\[\/url\]/is',
function($match) use ($this) {
return $this->_link($match[1], $match[2]);
},
$text);Здесь три «лишних» элемента:
- Ключевое слово
function— многословно. - Явное указание
use ($this)— избыточно, потому что$thisнужен почти всегда. - Фигурные скобки и оператор
return— занимают строки, не добавляя смысла.
Это не ошибка, но в проектах с десятками подобных обработчиков такой стиль делает код громоздким.
Современный вариант: Стрелочные функции
Начиная с PHP 7.4, можно использовать стрелочную функцию:
ВыделитьPHP
$text = preg_replace_callback(
'/\[url(.*?)\](.*?)\[\/url\]/is',
fn($m) => $this->_link($m[1], $m[2]),
$text);Что изменилось:
fn($m)вместоfunction($match).- Нет
use ($this):$thisавтоматически доступен внутри стрелочной функции. - Одно выражение после
=>заменяетreturn.
Код стал короче и понятнее.
Переход на fn в типовых случаях
Случай 1: Простой обработчик с $this
Было:
ВыделитьPHP
function($match) use ($this) {
return $this->process($match[1]);
}Стало:
ВыделитьPHP
fn($m) => $this->process($m[1])Случай 2: Обработчик, которому нужны внешние переменные
Было:
ВыделитьPHP
function($match) use ($prefix, $config) {
return $this->replace($prefix, $config, $match[1]);
}Стало:
ВыделитьPHP
fn($m) => $this->replace($prefix, $config, $m[1])Стрелочная функция автоматически захватывает все переменные из внешней области видимости — писать
use не нужно.Случай 3: Динамический шаблон с конкатенацией
Если шаблон собирается динамически, например, на основе переменной
$tag:Было:
ВыделитьPHP
$pattern = '/\[' . $tag . ':(.*?)\]/is';
$text = preg_replace_callback(
$pattern,
function($match) use ($tag, $this) {
return $this->handleTag($tag, $match[1]);
},
$text);Стало:
ВыделитьPHP
$pattern = '/\[' . preg_quote($tag, '/') . ':(.*?)\]/is';
$text = preg_replace_callback(
$pattern,
fn($m) => $this->handleTag($tag, $m[1]),
$text);Обратите внимание: Здесь добавлен
preg_quote — это хорошая практика, чтобы спецсимволы в $tag не ломали регулярку.Важные нюансы при обновлении
- Версия PHP. Стрелочные функции работают только в PHP 7.4 и выше. Если проект всё ещё на 7.3 или ниже, такой синтаксис вызовет ошибку.
- Многострочная логика. Стрелочная функция предназначена для одного выражения. Если внутри нужно несколько строк (циклы, условия, промежуточные переменные), лучше оставить обычную анонимную функцию.
- Читаемость. Если выражение становится слишком длинным, допустимо разбить аргументы на несколько строк — это всё равно будет стрелочная функция:ВыделитьPHP
$text = preg_replace_callback( $pattern, fn($m) => $this->render( $tag, $m[1], $options, $context ), $text);
Единообразие кода: Зачем это нужно
Когда в проекте все обработчики BBCode используют один стиль, это даёт несколько преимуществ:
- Проще читать. Не нужно каждый раз «переключаться» между разными стилями функций.
- Меньше ошибок. Меньше шансов забыть
use ($this)или ошибиться в фигурных скобках. - Легче рефакторить. Если позже понадобится вынести логику в отдельный метод, единый стиль упрощает поиск всех мест, где вызывается обработка.
- Современный вид. Код выглядит актуальным и соответствует современным стандартам PHP.
Практический совет по миграции
Если вы обновляете большой старый проект, делайте это поэтапно:
- Проверьте версию PHP на сервере.
- Выберите один тип обработчиков (например, только для простых тегов без сложной логики).
- Замените их на стрелочные функции.
- Прогоните тесты и проверьте, что парсинг работает как раньше.
- Постепенно обновляйте остальные обработчики.
Не стоит менять всё сразу — лучше двигаться небольшими, проверяемыми шагами.
Пример полного фрагмента
Вот как может выглядеть блок обработки нескольких тегов в современном стиле:
ВыделитьPHP
// [url]текст[/url]
$text = preg_replace_callback(
'/\[url(.*?)\](.*?)\[\/url\]/is',
fn($m) => $this->_renderLink($m[1], $m[2]),
$text);
// [img]путь[/img]
$text = preg_replace_callback(
'/\[img\](.*?)\[\/img\]/is',
fn($m) => $this->_renderImage($m[1]),
$text);
// [tag:param] — динамический тег
$tag = 'att';
$pattern = '/\[' . preg_quote($tag, '/') . ':(.*?)\]/is';
$text = preg_replace_callback(
$pattern,
fn($m) => $this->_handleTag($tag, $m[1]),
$text);Такой подход сохраняет всю функциональность старого кода, но делает его легче для восприятия и поддержки.
Переход на стрелочные функции — это не просто «синтаксический сахар». Это способ сделать код более чистым и единообразным, особенно в проектах, где обработка текста занимает значительную часть логики.