htmlentities() vs htmlspecialchars(): битва функций PHP

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

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

Начать курс

htmlentities() vs. htmlspecialchars(): подробное руководство с примерами

Вы когда-нибудь задумывались, почему в PHP есть две функции, которые делают, казалось бы, одно и то же? htmlentities() и htmlspecialchars() — это как два брата-близнеца: внешне похожи, но характеры разные. И выбор между ними может стать либо вашим супергеройским навыком, либо источником головной боли.

Если вы когда-либо задавали этот вопрос на Stack Overflow (а таких тысяч!), вы знаете, что ответ не всегда очевиден. Сегодня мы раз и навсегда разберемся, какая функция для чего нужна, когда использовать каждую из них, и как не попасть впросак с кодировками.

Поехали!

Что вообще делают эти функции?

Обе функции предназначены для экранирования HTML-символов. Простыми словами: они превращают специальные символы в их HTML-сущности, чтобы браузер отображал их как текст, а не интерпретировал как код.

Например, символ < превращается в &lt;. Это критически важно для:

  • Безопасности — защита от XSS-атак (межсайтового скриптинга)
  • Корректного отображения — чтобы ваш текст не «сломал» HTML-разметку

Но вот в чем подвох: htmlspecialchars() работает только с четырьмя символами, а htmlentities() — с всеми известными HTML-сущностями.

htmlspecialchars(): легкая артиллерия

Функция htmlspecialchars() преобразует только эти символы:

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

Этого набора достаточно для 99% случаев. Почему? Потому что только эти символы имеют специальное значение в HTML-разметке и могут сломать вашу страницу.

<?php
$user_input = '<script>alert("XSS")</script>';
echo htmlspecialchars($user_input, ENT_QUOTES, 'UTF-8');
// Выведет: &lt;script&gt;alert(&quot;XSS&quot;)&lt;/script&gt;
?>

htmlentities(): тяжелая кавалерия

htmlentities() — это тот самый перфекционист, который превращает в сущности все символы, имеющие HTML-эквивалент. Например, символы валют (€, £, ¥), математические знаки (∑, ∞, √) и даже стрелочки (←, ↑).

<?php
$text = 'Стоимость: 50€';
echo htmlentities($text, ENT_QUOTES, 'UTF-8');
// Выведет: Стоимость: 50&euro;
?>

Звучит удобно, правда? Но есть нюанс — производительность. htmlentities() работает медленнее, потому что обрабатывает больше символов. И если ваш сайт обрабатывает тысячи строк, разница становится заметной.

Ключевое отличие: кодировка

И вот тут мы подходим к самому важному моменту. Обе функции принимают третий параметр — кодировку. И если вы его не укажете, PHP будет использовать значение из директивы default_charset в php.ini (обычно это UTF-8).

Но htmlentities() особенно чувствительна к кодировке. Если вы укажете неправильную кодировку, функция может преобразовать символы некорректно. Например, с ISO-8859-1 некоторые символы UTF-8 будут потеряны.

<?php
// Плохой пример: кодировка не указана
echo htmlentities('Привет, мир!'); // Может выдать предупреждение

// Хороший пример: всегда указывайте кодировку
echo htmlentities('Привет, мир!', ENT_QUOTES, 'UTF-8');
?>

Когда использовать что?

Вот вам простая памятка:

Используйте htmlspecialchars(), когда:

  • Выводите пользовательские данные (комментарии, имена, сообщения)
  • Работаете с современным веб-приложением на UTF-8
  • Хотите максимальную производительность
  • Не ожидаете специальных символов вроде € или ©

Используйте htmlentities(), когда:

  • Выводите текст, который может содержать символы, отсутствующие в ASCII
  • Работаете со старыми системами или не UTF-8 кодировками
  • Нужно гарантировать, что любой символ будет отображен корректно
  • Готовы пожертвовать производительностью ради безопасности

Практический пример: форма комментариев

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

<script>alert('Хакнул!')</script>

Если вы выведете это без экранирования, браузер выполнит скрипт. Теперь сравните:

<?php
$comment = $_POST['comment'] ?? '';

// Вариант 1: без экранирования (ОПАСНО!)
echo $comment; // Скрипт выполнится!

// Вариант 2: htmlspecialchars (БЕЗОПАСНО)
echo htmlspecialchars($comment, ENT_QUOTES, 'UTF-8');
// Выведет текст, скрипт не выполнится

// Вариант 3: htmlentities (ТОЖЕ БЕЗОПАСНО, но медленнее)
echo htmlentities($comment, ENT_QUOTES, 'UTF-8');
// Тот же результат, но с избыточным преобразованием
?>

Флаги: настраиваем поведение

Обе функции поддерживают второй параметр — флаги. Вот самые полезные:

  • ENT_COMPAT — преобразует двойные кавычки, но не одинарные (по умолчанию)
  • ENT_QUOTES — преобразует и двойные, и одинарные кавычки
  • ENT_NOQUOTES — не преобразует кавычки вообще
  • ENT_SUBSTITUTE — заменяет некорректные последовательности символов на символ замены (U+FFFD)
<?php
$text = 'Кавычки: "двойные" и \'оди                

Блоги

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