Экранирование регулярного выражения в PHP
![Экранирование регулярного выражения в PHP](/images/articles/php-regexp-escaping.jpg)
Не так давно один из участников моего форума обнаружил ошибку у меня на сайте. Если ввести "/" в форму поиска, то выдавалась ошибка. Вроде бы ничего серьёзного, но это не очень хорошо. Поэтому эту ошибку я сразу нашёл и исправил. А ошибка была в том, что я кое-что забыл учесть. Это немного связано с экранированием регулярных выражений на PHP, и давайте разберём эту тему подробнее.
Любое регулярное выражение, которое составляется из того, что прислал пользователь, всегда надо пропускать через функцию preg_quote(). Данная функция добавляет обратный слэш перед каждым служебным символом, например, перед символом "*".
Зачем это нужно? Давайте рассмотрим такой пример:
<?php
$str = "abc * abc"; // Эта строка пришла от пользователя, например, методом POST
preg_match("/$str/", $text); // Поиск соответствия в некой переменной $text
?>
Но ведь наша цель была просто получить строку от пользователя без всяких спецсимволов (а "*" - это спецсимвол, соответствующий любому символу). А сам пользователь хотел, чтобы * была частью текста, а никак не спецсимволом. В результате, регулярное выражение работает не так, как требуется.
И данная проблема решается с помощью функции preg_quote():
<?php
$str = "abc * abc"; // Эта строка пришла от пользователя, например, методом POST
$str = preg_quote($str); // Экранируем служебные символы
preg_match("/$str/", $text); // Поиск соответствия в некой переменной $text
?>
Теперь "*" будет заменена на "\*", и никаких проблем при поиске соответсвия не возникнет, так как теперь "*" - это не более, чем часть текста, а не спецсимвол.
Вот на этом этапе я не ошибался, и всё сделал правильно, но я не учёл ещё кое-что:
<?php
$str = "abc / abc"; // Эта строка пришла от пользователя, например, методом POST
$str = preg_quote($str); // Экранируем служебные символы
preg_match("/$str/", $text); // Поиск соответствия в некой переменной $text
?>
После подстановки регулярное выражение станет таким: "/abc / abc/". Как Вы понимаете, оно работать не будет, и PHP выдаст ошибку.
Вот эту-то ошибку и обнаружил один из посетителей данного сайта. Решается она очень просто: все прямые слэши экранируются отдельно. Если Вы используете другой символ границы регулярного выражения (например, "#"), то надо экранировать его. Итак, вот правильный код:
<?php
$str = "abc / abc"; // Эта строка пришла от пользователя, например, методом POST
$str = preg_quote($str); // Экранируем служебные символы
$str = str_replace("/", "\/", $str); // Экранируем прямой слэш
preg_match("/$str/", $text); // Поиск соответствия в некой переменной $text
?>
Вот и всё решение проблемы. Давайте ещё раз подведём итог, что Вы должны делать:
- Экранировать регулярное выражение с помощью функции preg_quote().
- Экранировать символ границы регулярного выражения с помощью функции str_replace().
После этого проблем с ошибками регулярных выражений быть уже не должно.
-
-
Михаил Русаков
Комментарии (10):
Спасибо за фун-цию. Михаил, подскажите. Я добавляю в DOM новый элемент с помощью метода append(jquery), но скрипты для нового элемента уже не будут работать. Как с этим справится ? Задача вставить в таблицу новый товар, сразу после добавления и чтобы все события для нового элемента работали. Помогите пожалуйста.
Ответить
Всё должно работать, если добавив новый элемент Вы поставите ему все необходимые обработчики событий.
Ответить
Нет, после добавления нового элемента, создавать заново обработчики не вариант, там оч много событий. У меня таблица товаров в админ панели, при клике на поле таблицы, появляется поле для редактирования товара, при клике на строку таблицы строка выделяться и можно удалить выделенные товары. В общем там много событий. Но если добавить в таблицу новый товар с помощью append, то все события для нового элемента уже не работают.
Ответить
Не создать новые обработчики, а просто добавить соответствующие атрибуты во все вставляемые элементы. То есть не просто новый <div></div>, а <div onclick="func()"></div>
Ответить
Не, тоже не вариант. решение уже нашел. В общем у метода on() существует два способа обработки события. 1. Прямой 2. Делегированный. Прямой вот так: $('#items-back tbody tr').on('событие', function() {}). А делегированный вот так: $('#items-back tbody').on('click', 'tr', function() {}). Михаил добавте в коментарии форматирование текста, какой-то плагин на подобии tinymce.
Ответить
А вот хорошая статья, может пригодится. http://jquery.page2page.ru/index.php5/On
Ответить
Ну к примеру если вам необходимо добавить к новому(только что созданному) элементу что либо, обратитесь к нему используя live, к примеру: $("#new_element").live("click", function(){ $(this).after("<p>=)</p>"); });
Ответить
live не поддерживает submit, а у меня событие именно submit. К тому же live устарел и в новых версиях его совсем уберут. Обработчик событий .on()для того и создан чтобы объединить три метода .bind(), .delegate(), .live()
Ответить
$str = preg_quote($str); // Экранируем служебные символы $str = str_replace("/", "\/", $str); // Экранируем прямой слэш
Ответить
достаточно передать слеш вторым параметром в preg_quote
Ответить
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.