htmlentities() vs htmlspecialchars() в PHP: полный разбор с примерами

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

htmlentities() vs. htmlspecialchars(): битва титанов экранирования в PHP

Если вы хоть раз сталкивались с выводом пользовательских данных на веб-странице, то наверняка слышали о функциях htmlentities() и htmlspecialchars(). Это два главных инструмента PHP для защиты от XSS-атак и корректного отображения HTML-символов. Но в чем между ними разница? Какой выбрать новичку, а какой — профи? Давайте разберемся раз и навсегда.

Представьте: вы пишете блог на PHP, и пользователь вводит комментарий: <script>alert('XSS')</script>. Если вы просто выведете это на экран, браузер выполнит скрипт. Катастрофа! Тут на помощь приходят htmlspecialchars() и htmlentities(). Но каждый из них работает по-своему.

Что общего у htmlspecialchars() и htmlentities()?

Обе функции преобразуют специальные HTML-символы в их HTML-сущности (entities). Например:

  • & (амперсанд) → &amp;
  • < (меньше) → &lt;
  • > (больше) → &gt;
  • " (двойная кавычка) → &quot;
  • ' (одинарная кавычка) → &#039; (или &apos; в зависимости от флага)

Без них любой ввод с угловыми скобками или амперсандами сломает верстку или откроет дверь для хакеров.

Главное отличие: масштаб преобразования

Вот тут и кроется секрет. htmlspecialchars() — это экономный боец. Он преобразует только пять основных символов, которые имеют прямое значение в HTML:

  • &&amp;
  • <&lt;
  • >&gt;
  • "&quot;
  • '&#039; (если включен флаг ENT_QUOTES)

А htmlentities() — это перфекционист. Он преобразует все символы, для которых существуют HTML-сущности. Это не только угловые скобки, но и символы валют (€, £, ¥), математические знаки (∑, ∂), буквы с диакритическими знаками (é, ñ, ü) и даже смайлики (☺).

Простой пример: разница на практике

Давайте посмотрим на код. Допустим, у нас есть строка с французским текстом:

<?php
$text = "Café & thé <script>alert('test')</script>";
echo "htmlspecialchars: " . htmlspecialchars($text, ENT_QUOTES, 'UTF-8') . "<br>";
echo "htmlentities: " . htmlentities($text, ENT_QUOTES, 'UTF-8');
?>

Результат:

htmlspecialchars: Café & thé <script>alert('test')</script>
htmlentities: Café & thé <script>alert('test')</script>

В этом примере разницы нет, потому что символы "é" и другие латинские буквы не имеют специального значения в HTML. Но давайте попробуем с символами, которые имеют сущности:

<?php
$text = "€ 100 <b>bold</b>";
echo "htmlspecialchars: " . htmlspecialchars($text, ENT_QUOTES, 'UTF-8') . "<br>";
echo "htmlentities: " . htmlentities($text, ENT_QUOTES, 'UTF-8');
?>

Результат:

htmlspecialchars: € 100 <b>bold</b>
htmlentities: &euro; 100 <b>bold</b>

Видите? htmlentities() превратила символ евро "€" в его сущность &euro;. А htmlspecialchars() оставила его как есть. Почему? Потому что "€" не является опасным символом для HTML — браузер отобразит его корректно и без экранирования.

Когда использовать htmlspecialchars()?

Это ваш выбор по умолчанию. Используйте htmlspecialchars() в 99% случаев, когда вы выводите пользовательские данные:

  • Комментарии, сообщения, имена пользователей
  • URL-параметры (но лучше urlencode() для ссылок)
  • Любой текст, который может содержать HTML-теги или амперсанды
  • Вывод данных из базы данных

Почему? Потому что она быстрее, использует меньше памяти и делает ровно то, что нужно для безопасности — блокирует опасные символы. Все остальные символы (валюты, акценты, спецсимволы) браузер и так отобразит правильно, если вы используете кодировку UTF-8 (а вы должны ее использовать).

Правильный вызов с флагами:

<?php
echo htmlspecialchars($userInput, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
?>

Флаг ENT_QUOTES преобразует и одинарные, и двойные кавычки. ENT_SUBSTITUTE заменяет некорректные символы на символ замены вместо возврата пустой строки.

Когда использовать htmlentities()?

Ситуации, когда htmlentities() действительно нужна, довольно редки, но они есть:

  • Старые системы с кодировкой ISO-8859-1 (Latin-1): Если ваш сайт работает не в UTF-8 (что сейчас редкость), некоторые символы могут не отображаться. htmlentities() преобразует их в сущности, которые гарантированно отобразятся в любом браузере.
  • Генерация XML/HTML для старых парсеров: Некоторые древние парсеры не понимают UTF-8 и ожидают только ASCII. Тогда все не-ASCII символы нужно превратить в сущности.
  • Вывод в атрибуты HTML: Если вы вставляете данные в атрибут (например, value="..."), htmlentities() может быть избыточной, но иногда используется для подстраховки. Однако htmlspecialchars() с ENT_QUOTES справляется не хуже.
  • Работа с сущностями в старых email-рассылках: Некоторые почтовые клиенты плохо работают с UTF-8 в HTML-письмах.

Пример,

Блоги

Рекомендаций по книгам