#Когда возникает проблема и как её отличить
После перехода на PHP 8 preg_match() может предупреждать о некорректном шаблоне, возвращать false или перестать совпадать на данных другой кодировки. Конкретный результат зависит от регулярного выражения и версии PCRE; нельзя приписывать все сбои изменению языка.
#Возможные причины и диагностические признаки
| Возможная причина | Как узнать | Что делать |
|---|---|---|
| Некорректный шаблонВ шаблоне не закрыт разделитель, группа или использована недопустимая последовательность. | Журнал содержит preg_match(): Compilation failed | Проверить регулярное выражение и экранирование. |
| Неверная кодировка текстаВходные данные не являются корректным UTF-8. | При /u совпадение ломается лишь на некоторых старых строках | Проверить кодировку и преобразовать её на границе ввода. |
Ошибка обработки возвращаемого значенияТакой код смешивает «не найдено» (0) и ошибку (false). | Код делает if (!preg_match(...)) | Сравнивать результат оператором ===. |
#Пошаговая диагностика и исправление
- Найдите исходный шаблон и вызывающий кодОткройте журнал PHP и найдите первое предупреждение от
preg_match, файл и строку. В редакторе скопируйте используемое регулярное выражение и пример обезличенной строки, которая не проходит. Не проверяйте секретные идентификаторы в публичных сервисах для тестирования выражений. - Проверьте синтаксис разделителей и экранированиеУбедитесь, что шаблон имеет корректную форму, например
~^[0-9]+$~, и что внутренние символы-разделители экранированы или выбран другой разделитель. Если выражение содержит пользовательский текст, используйтеpreg_quote($text, "~")для буквального поиска вместо конкатенации с непроверенным вводом. - Разделите совпадение, отсутствие совпадения и ошибкуНа тестовой копии сохраните
$result = preg_match($pattern, $subject, $matches);. Если$result === 1, совпадение найдено;$result === 0означает отсутствие совпадения;$result === falseозначает ошибку исполнения. В последнем случае запишитеpreg_last_error_msg()в серверный журнал сразу после вызова и проверьте причину. - Проверьте UTF-8 для шаблонов с /uЕсли в шаблоне включён модификатор
u, убедитесь, что и шаблон, и обрабатываемая строка содержат допустимые UTF-8-байты. Для строк из старой Windows-1251 сначала выясните исходную кодировку и преобразуйте копию в UTF-8 с явным указанием источника. Удалениеuнаугад меняет правила сопоставления символов и может сломать проверку кириллицы. - Исследуйте проблему с длинной строкой отдельноЕсли на коротком тексте всё работает, а на длинном получается false, проверьте
preg_last_error()и признаки превышения ограничений обратного поиска или вложенности. Не увеличивайтеpcre.backtrack_limitбез измерений: сложное выражение может потреблять много ресурсов. Сначала попробуйте упростить повторения и якоря шаблона на тестовом стенде. - Прогоните контрольные примерыПодготовьте набор: подходящая строка, неподходящая строка, пустая строка, кириллица и длинный ввод. Выполните тест под фактической версией PHP 8 в копии приложения; сравните
1,0иfalseи убедитесь, что при ошибке появляется диагностическая запись, а не ложный отрицательный результат.
#Как проверить, что проблема устранена
На корректном вводе preg_match возвращает 1, при отсутствии совпадения — 0, а при сбое — false с диагностикой. После исправления не должно оставаться предупреждений о некорректном шаблоне и скрытых ошибок кодировки.
#Если ошибка осталась
Повторите исходный сценарий в тестовой среде, откройте свежую запись журнала с точным временем, именем функции, файлом и строкой. Сравните новое сообщение с исходным: ошибка могла переместиться на следующий участок кода. Не подавляйте все ошибки общим обработчиком. Если изменения затрагивали работающий проект, восстановите сохранённую копию и разберите новое сообщение до повторного переноса.