PHP: как убрать HTML теги из текста?

Проверка и обработка входящих данных является одной из распространённых задач в программировании. Язык PHP обычно используется для веб-приложений, поэтому здесь наиболее актуально удаление HTML тегов из текста, ведь именно они наиболее подверженны сторонним инъекциям. В данной статье я хочу напомнить Вам о старичке stip_tags() и его фишках, а также предложить решения для удаления секционных HTML тегов и ещё парочку полезных бонусов вдогонку.

И так. Основным нашим инструментом для удаления HTML тегов из текста является функция strip_tags(). Мы передаём ей строковое значение, а она удаляет из него HTML и PHP теги, например:

$s = '<p>Параграф.</p><!-- Комментарий --> <a href="/2014/08/">Еще текст</a>.';
echo strip_tags($s);

Этот пример выведет строку:

Параграф. Еще текст.

Примечательно здесь то, что у функции имеется и второй (не обязательный, но полезный) параметр, значением которого является строка с перечнем разрешенных HTML тегов, например:

$s = '<p>Параграф.</p><!-- Комментарий --> <a href="/2014/08/">Еще текст</a>.';
echo strip_tags($s, '<p><a>');

Этот пример выведет строку:

<p>Параграф.</p> <a href="/2014/08/">Еще текст</a>.

По моему, очень удобно. Тем не менее, это не решает одну важную проблему – удаление секционных HTML тегов, например: script, noscript и style – они наиболее распространённые. Когда мне нужно убрать такие секционные теги, а также варианты начинающиеся с «<» и заканчивающиеся символом «>», я использую следующий PHP код:

$p = array(
  "'<script[^>]*?>.*?</script>'si",
  "'<noscript[^>]*?>.*?</noscript>'si",
  "'<style[^>]*?>.*?</style>'si",
  "'<[\/\!]*?[^<>]*?>'si",
);
$r = array(" "," "," "," ");
$s = preg_replace($p, $r, $s);

Здесь переменная $p содержит массив регулярных выражений, а $r – массив соответствующей их замены (я использую пробелы). Осталось лишь провести замену в строке, и мы уберём HTML мусор из текста.

Очевидно, что два выше приведённых решения можно совместить. В начале я использую замену через регулярные выражения, а потом strip_tags() и у меня получается своя функция nohtml().

Напоследок хочу предложить Вам ещё несколько полезных решений. Так в тексте лучше заменить табуляцию пробелом, результат интерпретации того и другого в браузере идентичны, а хлопот будет меньше, например:

$s = str_replace("\t", " ", $s);

Если Вам не нужны переносы строк, их тоже можно заменить пробелами, например:

$s = str_replace(array("\n", "\r"), " ", $s);

От лишних же пробелов можно избавиться простым регулярным выражением, например:

$s = preg_replace("/\s+/", ' ', $s);
$s = trim($s); // будет не лишним

На этом у меня всё. Спасибо за внимание. Удачи!