Функция preg_match_all() принимает 3 параметра: шаблон поиска, сам текст и переменную, в которую эта функция сохранит результаты поиска.
Поскольку функция возвращает количество найденных строк (или false в случае ошибки), мы можем сразу подставить её в оператор if.
Массив с результатами поиска (в нашем случае $result) состоит из двух частей: в $result[0] будут найденные строки вместе с открывающим и закрывающим тегами span, а в $result[1] будут те же строки без тега span, т.е. тот текст, что находится в круглых скобках.
Маска регулярного выражения находится между вертикальными чертами | . В шаблоне (.*) точка означает любой символ, звёздочка — любое количество символов (т.е. суммарно получаем «любое количество любых символов»).
Скобки говорят, что найденный текст нам нужно получить отдельно. Без скобок мы получим только $result[0], а $result[1] не будет существовать.
Чтобы найти только не пустые теги, можно заменить .* на .+ . Плюсик означает любое количество символов, но не меньше одного.
Uis — модификаторы. U означает работу с UTF-8, i — регистронезависимый поиск, s — что символ точка включает в себя переносы строк, т.е. поиск будет по всем строкам, а не по одной.
Простая замена текста или тегов (preg_replace)
Заменить текст без замены тегов можно следующим образом:
$1 и $2 содержат открывающий и закрывающий теги соответственно, поскольку мы поместили их в скобки.
А в следующем примере меняются только теги, сам текст остаётся нетронутым:
Строки один и два в тексте.'; $new_text = preg_replace('|(.*)()|Uis', '$1', $text); echo $new_text; //
Строки один и два в тексте.
Замена текста собственной функцией (preg_replace_callback)
Самое вкусное. Допустим, мы хотим использовать на сайте что-то вроде BBCode, т.е. собственные теги, которые потом должны заменяться на обычный HTML код:
Заменить тег на обычный HTML тег можно так:
Заголовок
'; $new_text = preg_replace_callback('|
(.*)
|Uis', function($matches) < return '
' . $matches[1] . '
'; >, $text); echo $new_text;
Функция preg_replace_callback передаёт каждую найденную строку в нашу безымянную функцию, затем заменяет найденный текст на то, что наша функция возвращает.
Не знаком с безымянными функциями? Тогда можно сделать так:
function replaceH1($matches) < return '
' . $matches[1] . '
'; > $text = '
Заголовок
'; $new_text = preg_replace_callback('|
(.*)
|Uis', 'replaceH1', $text); echo $new_text;
Вторым параметром передаём название нашей функции. Код отработает точно также, как и предыдущий.
Вывод фрагментов исходного HTML и PHP кода
Частая проблема разработчиков, которым хочется вести свой блог. Есть HTML статья, внутри которой некоторые фрагменты кода нужно прогонять через htmlspecialchars() , чтобы они выводились как обычный текст:
$text ='
Пример кода
Этот текст не должен быть жирным
Какое-то описание кода выше.
Второй не жирный текст ';
Теперь в этом нет ничего сложного:
$text = '
Пример кода
Этот текст не должен быть жирным
Какое-то описание кода выше.
Второй не жирный текст '; $new_text = preg_replace_callback('|(.*)|Uis', function($matches) < return htmlspecialchars($matches[1], ENT_QUOTES, 'UTF-8'); >, $text); echo $new_text;
Продвинутый BBCode с атрибутами
Иногда описанного выше функционала бывает недостаточно, например если нужно передать в функцию какие-либо параметры:
Вместо собственного велосипеда рекомендую использовать готовую библиотеку Shortcode.
В ней из коробки уже есть возможность использования атрибутов, а также события и куча других полезных фишек. Вот как может выглядеть пример обработки тега с атрибутами:
use Thunder\Shortcode\ShortcodeFacade; $text = 'текст с тегами'; $shortcode = new ShortcodeFacade(); $shortcode->addHandler('link', function($s) < $content = $s->getContent(); $url = $s->getParameter('url'); $title = $s->getParameter('title'); if(!$title) $title = 'Стандартный заголовок'; // Ещё какие-нибудь действия return $content; >); $new_text = $shortcode->process($text);
Только нужно учесть, что в Shortcode по-умолчанию парсятся атрибуты в квадратных скобках [] . Я и сам использую квадратные, но в примерах использовал фигурные, чтобы избежать возможных конфликтов тегов на этом сайте.
Для начала давайте разберемся, в чем различие активной ссылки и неактивной. Представим, что мы размещаем простой текст, в котором есть ссылки, либо email адреса. Так как текст отображается в браузере, у нас появляется возможность оформить ссылку согласно синтаксису разметки HTML, после чего ссылка будет открывать ресурс при клике по ней. Иными словами в этом случае ссылка становится не просто строкой, а активной ссылкой, оформленной согласно синтаксису HTML. Именно это и определяет является ли ссылка активной либо нет.
На некоторых сайтах можно повстречать текст, в которых есть неактивные ссылки. Такие ссылки могут быть следствием отсутствия базовых навыков оформления ссылок у пользователей, которые размещают текст. Бывают и случаи когда их не оформляют специально, по ряду каких либо причин, но суть не в этом. Давайте рассмотрим пример, как можно найти все ссылки в тексте и сделать их активными. Для поиска ссылок и email адресов в тексте мы воспользуемся регулярными выражениями. Для удобства использования оформляем код в виде функции:
Теперь о минусах данного примера. Нужно понимать, что чем больше у вас текст, тем дольше происходит его обработка, и нагрузка на процессор вашего сервера. Это означает, что ссылки следует преобразовывать ещё до момента записи текста в базу, т.е. конечным посетителям сайта текст должен показываться уже с преобразованными ссылками ещё на стадии его добавления.
Функция preg_match_all() принимает 3 параметра: шаблон поиска, сам текст и переменную, в которую эта функция сохранит результаты поиска.
Поскольку функция возвращает количество найденных строк (или false в случае ошибки), мы можем сразу подставить её в оператор if.
Массив с результатами поиска (в нашем случае $result) состоит из двух частей: в $result[0] будут найденные строки вместе с открывающим и закрывающим тегами span, а в $result[1] будут те же строки без тега span, т.е. тот текст, что находится в круглых скобках.
Маска регулярного выражения находится между вертикальными чертами | . В шаблоне (.*) точка означает любой символ, звёздочка — любое количество символов (т.е. суммарно получаем «любое количество любых символов»).
Скобки говорят, что найденный текст нам нужно получить отдельно. Без скобок мы получим только $result[0], а $result[1] не будет существовать.
Чтобы найти только не пустые теги, можно заменить .* на .+ . Плюсик означает любое количество символов, но не меньше одного.
Uis — модификаторы. U означает работу с UTF-8, i — регистронезависимый поиск, s — что символ точка включает в себя переносы строк, т.е. поиск будет по всем строкам, а не по одной.
Простая замена текста или тегов (preg_replace)
Заменить текст без замены тегов можно следующим образом:
$1 и $2 содержат открывающий и закрывающий теги соответственно, поскольку мы поместили их в скобки.
А в следующем примере меняются только теги, сам текст остаётся нетронутым:
Строки один и два в тексте.'; $new_text = preg_replace('|(.*)()|Uis', '$1', $text); echo $new_text; //
Строки один и два в тексте.
Замена текста собственной функцией (preg_replace_callback)
Самое вкусное. Допустим, мы хотим использовать на сайте что-то вроде BBCode, т.е. собственные теги, которые потом должны заменяться на обычный HTML код:
Заменить тег на обычный HTML тег можно так:
Заголовок
'; $new_text = preg_replace_callback('|
(.*)
|Uis', function($matches) < return '
' . $matches[1] . '
'; >, $text); echo $new_text;
Функция preg_replace_callback передаёт каждую найденную строку в нашу безымянную функцию, затем заменяет найденный текст на то, что наша функция возвращает.
Не знаком с безымянными функциями? Тогда можно сделать так:
function replaceH1($matches) < return '
' . $matches[1] . '
'; > $text = '
Заголовок
'; $new_text = preg_replace_callback('|
(.*)
|Uis', 'replaceH1', $text); echo $new_text;
Вторым параметром передаём название нашей функции. Код отработает точно также, как и предыдущий.
Вывод фрагментов исходного HTML и PHP кода
Частая проблема разработчиков, которым хочется вести свой блог. Есть HTML статья, внутри которой некоторые фрагменты кода нужно прогонять через htmlspecialchars() , чтобы они выводились как обычный текст:
$text ='
Пример кода
Этот текст не должен быть жирным
Какое-то описание кода выше.
Второй не жирный текст ';
Теперь в этом нет ничего сложного:
$text = '
Пример кода
Этот текст не должен быть жирным
Какое-то описание кода выше.
Второй не жирный текст '; $new_text = preg_replace_callback('|(.*)|Uis', function($matches) < return htmlspecialchars($matches[1], ENT_QUOTES, 'UTF-8'); >, $text); echo $new_text;
Продвинутый BBCode с атрибутами
Иногда описанного выше функционала бывает недостаточно, например если нужно передать в функцию какие-либо параметры:
Вместо собственного велосипеда рекомендую использовать готовую библиотеку Shortcode.
В ней из коробки уже есть возможность использования атрибутов, а также события и куча других полезных фишек. Вот как может выглядеть пример обработки тега с атрибутами:
use Thunder\Shortcode\ShortcodeFacade; $text = 'текст с тегами'; $shortcode = new ShortcodeFacade(); $shortcode->addHandler('link', function($s) < $content = $s->getContent(); $url = $s->getParameter('url'); $title = $s->getParameter('title'); if(!$title) $title = 'Стандартный заголовок'; // Ещё какие-нибудь действия return $content; >); $new_text = $shortcode->process($text);
Только нужно учесть, что в Shortcode по-умолчанию парсятся атрибуты в квадратных скобках [] . Я и сам использую квадратные, но в примерах использовал фигурные, чтобы избежать возможных конфликтов тегов на этом сайте.