esc_attr() — подготавливает строку для использования в HTML-атрибуте

Если вы откроете исходный код ядра WordPress или какого-нибудь плагина, то скорее всего вы заметите, что значения атрибутов перед выводом пропускаются через функцию esc_attr().

Что конкретно делает функция: преобразует символы < > & " ' в HTML-сущности, а именно в
&lt; &gt; &amp; &quot; &#039; соответственно. Повторное преобразование не производится.

Общий принцип здесь такой, что мы не должны доверять никакому источнику данных, и если база данных была взломана, и мы из неё получаем, скажем для атрибута alt="" изображения, подобный текст "><script>код майнинга, то ничего плохого не произойдёт, разве что внутри атрибута alt будет какая-то дичь. Подробнее про очистку данных рекомендую посмотреть мой отдельный видеоурок.

Также есть похожие функции – esc_attr__() и esc_attr_e() – они нужны при работе с локализацией.

esc_attr( $text )

Параметры

$text
(строка) Текст, который планируется использоваться в качестве значения HTML-атрибута.

Примеры

1. Результат действия функции

$text = "<span>(тег) '(кавычка) \"(двойная кавычка) &(амперсанд)";
echo esc_attr( $text );
 
// Будет выведено
// &lt;span&gt;(тег) &#039;(кавычка) &quot;(двойная кавычка) &amp;(амперсанд)

Обратный слэш \ кстати исчез, потому что он вообще никак не участвует в строке, он нужен лишь для того, чтобы в неё можно было добавить двойные кавычки (ведь сама строка в двойных кавычках).

2. Спасаемся от взломанной базы данных

Чуть выше я упоминал пример с изображением и атрибутом alt. Пришло время разобрать его по шагам, почему бы и нет.

$alt = // получили из базы данных что-то
echo '<img src="" alt="' . $alt . '" />';

Так вот, что если в базу данных каким-то образом загнали JavaScript-код майнинга (предположим), и мы получаем оттуда значения для alt равное "><script>код майнинга</script>

Тогда, когда оно подставится в alt атрибут, мы получим, что атрибут alt закроется, тег <img> закроется, и начнёт выполняться тег <script>. А после ещё выведется обычным текстом />.

<img src="" alt=""><script>код майнинга</script> />

Однако, если мы защитим атрибут функцией esc_attr(), вот так:

$alt = // получили из базы данных что-то
echo '<img src="" alt="' . esc_attr( $alt ) . '" />';

Тогда весь вредоносный код будет проэкранирован и он никак не выполнится, лишь выведется внутри атрибута alt.

<img src="" alt="&quot;&gt;&lt;script&gt;код майнинга&lt;/script&gt;" />

3. Двойное экранирование

Выше я упоминал, что если у вас в строке уже есть HTML-сущности, то повторному экранированию они подвергнуты не будут, то есть &lt; не превратится в &amp;lt;.

Окей, а что делать, если вам это нужно сделать? Тут нас может выручить PHP-функция htmlspecialchars().

$text = "&lt;span&gt;";
echo esc_attr( $text );         // &lt;span&gt;
echo htmlspecialchars( $text ); // &amp;lt;span&amp;gt;

4. Использование в формах

В интернете можно встретить пример по использованию функции esc_attr() внутри атрибута value в поле формы. Он примерно такой:

$fname = ( isset( $_POST['fname'] ) ) ? $_POST['fname'] : '';
echo '<input type="text" name="fname" value="' . esc_attr( $fname ) . '">';

Но к этому примеру важно добавить некоторые пояснения, и я сейчас их и добавлю.

Итак, при использовании функции для очистки атрибута value в формах, вы будете терять HTML-сущности!

Предположим, что у нас есть какой-то текст в базе данных, содержащий экранированный HTML-тег и обычные двойные кавычки, например Используйте тег "br" (&lt;br&gt;). А также у нас есть обычное текстовое поле, значение которого очищается функцией esc_attr().

echo '<input type="text" value="' . esc_attr( $value ) . '">';

Подставим в value значение из базы данных?

<input type="text" value="Используйте тег &quot;br&quot; (&lt;br&gt;).">

Но (!) браузер обрабатывает HTML-сущности внутри полей формы и пользователю отобразится: Используйте тег "br" (<br>), и поля в принципе так работают, что и значение поля станет таким же. А значит, при отправке формы и сохранении её в базу данных мы теряем все HTML-сущности в строке и значение в базе данных становится Используйте тег "br" (<br>).

В таком случае ситуацию поможет спасти использование esc_textarea(), которая осуществляет повторные преобразования.

esc_attr: <input value="Используйте тег &quot;br&quot; (&lt;br&gt;)">
esc_textarea: <input value="Используйте тег &quot;br&quot; (&amp;lt;br&amp;gt;)">
Пример использования функций esc_attr() и esc_textarea() в качестве значений полей формы
Пример того, как это будет выглядеть в форме при использовании esc_attr() и при использовании esc_textarea() соответственно.

Хуки

attribute_escape

К возвращаемую результату функции esc_attr() дополнительно применяется фильтр-хук attribute_escape, который позволяет модифицировать очищенное значение.

return apply_filters( 'attribute_escape', $safe_text, $text );
$safe_text
(строка) Очищенный функцией текст.
$text
Оригинальный текст, переданный в функцию.

В дополнении предыдущего примера, покажу вам, как при помощи этого фильтра не очищать одну определённую строку.

add_filter( 'attribute_escape', 'true_skip_escaping_specific_string', 25, 2 );
 
function true_skip_escaping_specific_string( $safe_text, $text ) {
 
	if( 'Используйте тег "br" (&lt;br&gt;)' === $text ) {
		return $text;
	}
	return $safe_text;
 
}

Не знаете, как работать с фильтрами? Смотрите этот урок.

Миша

Впервые познакомился с WordPress в 2009 году. Организатор и спикер на конференциях WordCamp. Преподаватель в школе Нетология.

Пишите, если нужна помощь с сайтом или разработка с нуля.

Чтобы оставить комментарий, пожалуйста, зарегистрируйтесь или войдите.

Миша Рудрастых и WordPress

Полезности из мира WordPress и жизни студии.

Мой телеграм-канал