- Опубликовано: 6 мар 2025
- 62
Разница между `{{ }}` и `{!! !!}` в шаблонах Blade Laravel
Введение
Blade – это встроенный в Laravel мощный и удобный шаблонизатор для создания представлений (view). Он позволяет смешивать PHP-код с HTML аккуратно и безопасно. В отличие от некоторых других шаблонизаторов, Blade не ограничивает вас в использовании чистого PHP в шаблонах. Все Blade-шаблоны компилируются в нативный PHP и кешируются, поэтому добавляют практически нулевые накладные расходы на производительность вашего приложения (Blade Templates - Laravel 11.x - The PHP Framework For Web Artisans). Шаблоны Blade имеют расширение .blade.php
и обычно хранятся в каталоге resources/views
.
Преимущества Blade для разработчиков Laravel:
-
Простой синтаксис. Blade предоставляет понятные директивы (
@if
,@foreach
и др.) и выражения в фигурных скобках для вывода данных, делая шаблоны более читаемыми по сравнению с чистым PHP. -
Наследование шаблонов. Вы можете определять основной макет (layout) и «наследовать» его в дочерних шаблонах через секции
@section
и@yield
. Это позволяет переиспользовать код и поддерживать единый стиль страниц. -
Включение подшаблонов. Легко разбивать интерфейс на мелкие части и подключать их через
@include
,@component
и т.д., что улучшает организацию кода. - Безопасный вывод по умолчанию. Blade автоматически экранирует (escaping) вывод переменных, защищая приложение от инъекций HTML/JS (XSS-атак). Это одно из ключевых отличий Blade, о котором мы поговорим далее.
В этой статье мы подробно рассмотрим разницу между синтаксисом вывода переменных {{ }}
и {!! !!}
в Blade, приведем примеры использования каждого и обсудим вопросы безопасности при выводе данных.
Различия между {{ }}
и {!! !!}
В Blade для вывода переменных в шаблоне используются фигурные скобки. Существуют два основных варианта синтаксиса:
-
{{ $variable }}
– двойные фигурные скобки, обычный вывод. -
{!! $variable !!}
– фигурные скобки с восклицательными знаками, raw-вывод (неэкранированный).
Что делает {{ }}
: При использовании {{ $variable }}
Blade экранирует содержимое переменной, автоматически пропуская данные через функцию PHP htmlspecialchars
(Blade Templates - Laravel 11.x - The PHP Framework For Web Artisans). Это означает, что все специальные символы HTML (например, <
, >
, &
и кавычки) будут преобразованы в безопасные эквиваленты (<
, >
, &
и т.д.) прежде чем отдать их браузеру. Экранирование предотвращает выполнение произвольного HTML и JavaScript в браузере пользователя, защищая от XSS-атак (межсайтового скриптинга).
Пример:
<?php $name = "<b>John Doe</b>"; ?> <!-- Blade шаблон: --> Привет, {{ $name }}!
Если переменная
$name
содержит строку"<b>John Doe</b>"
, то конструкция{{ $name }}
выведет в HTML<b>John Doe</b>
. В результате пользователь увидит на странице буквальный текст<b>John Doe</b>
, а тег<b>
не будет интерпретирован как жирное начертание. Проще говоря, Blade отобразил угловые скобки, вместо того чтобы браузер воспринял их как часть разметки.
Как работает {!! !!}
: Синтаксис {!! $variable !!}
, напротив, не экранирует содержимое. Данные выводятся "как есть", без каких-либо преобразований. Это означает, что если строка содержит HTML-теги или JavaScript, они будут вставлены в итоговый HTML-документ сырыми. Браузер при выводе такого содержимого интерпретирует теги и скрипты, а не показывает их как текст.
Пример: Возьмем ту же переменную
$name = "<b>John Doe</b>"
.<!-- Blade шаблон: --> Привет, {!! $name !!}!
Использование
{!! $name !!}
выведет строку со сохраненными HTML-тегами. В итоговом HTML будет<b>John Doe</b>
, и браузер отобразит John Doe жирным шрифтом.
Важно: здесь<b>
-тег не был экранирован, и браузер применил его как форматирование.
Из приведенных примеров видно ключевое отличие: {{ }}
выводит безопасный текст (экранируя спецсимволы), а {!! !!}
выводит непосредственный HTML/скрипт (ничего не экранируя).
Когда использовать {{ }}
: Почти всегда предпочтительно использовать двойные фигурные скобки. Любые данные, полученные от пользователя, из базы данных или внешних источников, следует выводить через {{ }}
. Это гарантирует, что если данные содержат случайно или намеренно вставленный HTML/JS, он не сломает страницу и не приведет к уязвимостям. Проще говоря, {{ }}
— ваш дефолт для безопасного отображения переменных.
Когда использовать {!! !!}
: Сырые необработанные скобки нужны в ситуациях, когда вы намеренно хотите вставить HTML-разметку или скрипт, содержащийся в переменной. Например:
- Вы храните в базе данных заранее безопасный фрагмент HTML (например, от администратора сайта или из доверенного WYSIWYG-редактора) и хотите отрендерить его на странице.
- Вы генерируете HTML в самом приложении (например, формируете список в виде HTML-строки) и уверены, что он безопасен.
- Вам нужно встроить на страницу сторонний HTML-код (например, виджет или embed-код), полученный из надежного источника.
Во всех этих случаях {!! !!}
позволит отобразить содержимое переменной с сохранением HTML-разметки. Однако разработчик берёт на себя ответственность за безопасность такого вывода. Никогда не используйте {!! !!}
для данных, которым нельзя полностью доверять.
Важно: В современных версиях Laravel (5.x и новее) двойные скобки всегда экранируют вывод, а {!! !!}
– никогда. Если вы встречаете упоминание тройных фигурных скобок ({{{ }}}
), знайте, что это синтаксис из Laravel 4, где двойные скобки не экранировали, а тройные экранировали. Начиная с Laravel 5 эта путаница устранена: теперь используется одна форма {{ }}
для экранирования и альтернативная форма {!! !!}
для неэкранированного вывода.
Примеры кода
Рассмотрим несколько примеров, демонстрирующих использование {{ }}
и {!! !!}
на практике.
Пример 1: Базовое использование
Предположим, контроллер передает во view переменную $message
со значением, содержащим HTML-разметку:
// Контроллер (пример):
$message = "<i>Спасибо за регистрацию!</i>";
return view('welcome', ['message' => $message]);
В Blade-шаблоне welcome.blade.php
вы можете вывести эту переменную двумя способами:
<!-- welcome.blade.php -->
<p>С использованием {{ }}: {{ $message }}</p>
<p>С использованием {!! !!}: {!! $message !!}</p>
Результат:
-
Через
{{ }}
: на странице отобразится текст<i>Спасибо за регистрацию!</i>
со всеми символами<
и>
. Пользователь увидит угловые скобки, а слово "Спасибо за регистрацию!" останется без наклона. То есть браузер не применил тег<i>
(курсив). -
Через
{!! !!}
: на странице отобразится Спасибо за регистрацию! курсивом. Тег<i>
не был экранирован и интерпретировался браузером как наклонное начертание. Пользователь не увидит угловых скобок – вместо них сработает форматирование текста.
Этот пример иллюстрирует, что для вывода HTML-разметки из переменной необходимо использовать {!! !!}
. Если же использовать обычные двойные скобки, HTML появится как простой текст.
Пример 2: Рендеринг пользовательских данных в цикле
Часто шаблоны отображают списки данных, например, список пользователей с информацией о них. Предположим, у нас есть коллекция объектов $users
, и у каждого пользователя есть поля name
(имя) и bio
(описание). Пользовательское описание может содержать разметку (скажем, администратор разрешил в описании использовать ограниченный HTML для форматирования текста).
Мы хотим вывести имена пользователей и их описания:
<ul>
@foreach($users as $user)
<li>
<strong>{{ $user->name }}:</strong>
{!! $user->bio !!}
</li>
@endforeach
</ul>
Что тут происходит:
-
{{ $user->name }}
– мы выводим имя пользователя безопасно. Предполагается, что имя – обычный текст, и экранирование не повредит отображению. Если вдруг полеname
содержит что-то вроде<script>...
, Blade экранирует это, и никакой скрипт не выполнится. Обычно имя не содержит HTML, но мы подстраховываемся на случай попытки инъекции. -
{!! $user->bio !!}
– выводим «био» без экранирования, позволяя HTML-тегам отрендериться. Мы так делаем только потому, что доверяем содержимомуbio
(например, ограничили список разрешенных тегов при сохранении или контент вводится администратором). В результате в пункте списка<li>
описание пользователя появится с тем оформлением, которое в него заложено (переносы строк, ссылки, выделения и т.п.).
Если бы мы использовали для bio
конструкцию {{ $user->bio }}
, то все теги внутри описания отобразились бы как текст, и форматирование бы потерялось. С другой стороны, если выводить сырые данные, нужно убедиться, что в bio
не затесался вредоносный код.
Пример 3: Вставка HTML фрагмента через переменную
Иногда разработчики хранят в переменных или конфигурации небольшие HTML-фрагменты, которые нужно вставить в страницу. Допустим, у нас в переменной $banner
хранится HTML-код баннера:
$banner = '<div class="banner"><img src="/promo.jpg" alt="Акция"></div>';
Чтобы вывести этот баннер в шаблоне Blade, используйте сырой вывод:
{!! $banner !!}
Если применить обычные скобки ({{ $banner }}
), то вы просто увидите на странице текст <div class="banner">...
и тэги img
как текст – баннер не будет работать. Через {!! !!}
же HTML-разметка баннера интегрируется в страницу, и изображение отобразится.
Обратите внимание: подобные фрагменты обычно полностью контролируются разработчиком или контент-менеджером. Никогда не подставляйте таким образом произвольный пользовательский ввод.
Пример 4: Директивы Blade и вывод данных
Стоит понимать, что конструкции {{ }}
и {!! !!}
– это не директивы Blade, а синтаксис для вывода переменных. Их можно использовать внутри любых Blade-директив, таких как условные операторы и циклы, как мы уже показали. Если вам нужно буквально вывести что-то вроде {{ ... }}
(например, при использовании JavaScript-фреймворка Vue или Angular, где аналогичные шаблоны), Blade предоставляет символ @
для экранирования своих инструкций.
Пример, как вывести фигурные скобки, не обрабатывая их Blade-шаблонизатором:
<p>Blade не тронет: @{{ variable }}</p>
Результат в HTML будет <p>Blade не тронет: {{ variable }}</p>
. Блейд убрал @
, но оставил выражение {{ variable }}
нетронутым для дальнейшей обработки на стороне JS-фреймворка. Это редкий случай, но о нем стоит знать. Он показывает, что Blade по умолчанию воспринимает {{ }}
как команду вывода, и у нас есть средства избегать этого поведения при необходимости. Однако к теме экранирования HTML это имеет косвенное отношение – просто будьте внимательны, когда шаблоны Blade пересекаются с другими системами шаблонов.
Безопасность и потенциальные ошибки
В веб-разработке безопасность вывода данных – критически важна. Неправильное использование шаблонов может привести к уязвимостям, в частности к XSS (Cross-Site Scripting). Рассмотрим, какие риски существуют и как их предотвратить:
-
XSS-атаки при сырых данных. Если вы выводите данные через
{!! !!}
без должной очистки, злоумышленник может внедрить в них вредоносный скрипт. Например, предположим, что приложение выводит комментарий пользователя сырым способом:{!! $comment !!}
Если недоброжелатель введёт в комментарий что-то вроде
<script>alert('Hacked');</script>
, то при загрузке страницы этот скрипт выполнится. Злоумышленник может украсть cookie пользователей, исказить содержимое страницы, выполнить произвольные действия от имени пользователя и т.д. Blade с двойными скобками предотвратил бы это, преобразовав<script>
в безвредный текст<script>
. При сырых же скобках защита отсутствует. -
Всегда экранируйте пользовательский ввод. Правило номер один – любые данные, полученные извне (от пользователя, из URL, из базы, API), должны выводиться через
{{ }}
, если только вы их специально не очистили. Laravel Blade специально делает двойные фигурные скобки экранирующими по умолчанию, поэтому придерживайтесь этого соглашения. В документации Laravel подчёркивается: «Будьте очень осторожны, выводя контент, предоставленный пользователями вашего приложения. Обычно следует использовать экранирующий синтаксис с двойными фигурными скобками, чтобы предотвратить XSS-атаки при отображении данных, введённых пользователями» (Blade Templates - Laravel 11.x - The PHP Framework For Web Artisans). -
Используйте
{!! !!}
только для доверенных данных. Сырый вывод должен быть исключением, а не правилом. Применяйте его, только если уверены в безопасности контента. Например, HTML-разметка, которую ввел администратор через панель управления и которая прошла фильтрацию, или статичный код, захардкоженный в приложении. Самый безопасный подход – применять необработанный вывод лишь тогда, когда вы точно знаете, что это безопасно. В иных случаях, найдите способ обойтись экранированным выводом. -
Потенциальные ошибки новичков: Частая ошибка – использовать
{!! !!}
"на всякий случай" или из непонимания. Некоторые начинающие разработчики могут ставить сырой вывод, думая, что так "надежнее покажется всё, что нужно". На деле же это открывает дверь для уязвимостей. Обратная ситуация – забыть поставить{!! !!}
там, где требуется отобразить HTML. Тогда вы заметите, что страница показывает лишние символы (<
>
и т.д.). Решение – просто заменить на сырой вывод в нужном месте. Запомните правило: по умолчанию экранировать, и только при необходимости — раскрывать. -
Очистка и фильтрация HTML. В случаях, когда вам действительно нужно отображать пользовательский ввод с форматированием (например, комментарии с ограниченными тегами, описания с Markdown-разметкой, которая превращается в HTML), подумайте о предварительной санитизации данных. Можно использовать библиотеку типа HTMLPurifier или встроенные функции, чтобы вырезать опасные теги/атрибуты (скрипты, iframe, onmouseover и т.д.), оставив только безопасный поднабор HTML. После такой очистки вывод через
{!! !!}
станет менее рискованным. Тем не менее, даже при фильтрации, относитесь к raw-выводу с осторожностью. -
Double encoding (двойное экранирование). Laravel по умолчанию защищен от двойного экранирования. Это значит, что если ваша строка уже содержит HTML-сущности (например,
&
,<
и т.п.), Blade не будет экранировать&
повторно. Он умный в этом плане. Поэтому обычно не возникает проблемы, что вы экранировали данные дважды. Но знать про это стоит: не нужно пытаться вручную декодировать что-то перед передачей в Blade; оставьте эту работу шаблонизатору.
Подведём итог по безопасности: никогда не выводите неочищенные данные от пользователей без экранирования. Используйте Blade-выражения с двойными скобками для всего пользовательского ввода. Сырые выражения {!! !!}
применяйте только для контента, которому доверяете или который прошёл очистку. Такой дисциплинированный подход убережёт ваше приложение от большинства XSS-уязвимостей.
Заключение
Шаблонизатор Blade в Laravel значительно упрощает работу с представлениями, предлагая лаконичный синтаксис и заботясь о безопасности по умолчанию. Разница между конструкциями {{ }}
и {!! !!}
сводится к экранированию вывода: первые всегда защищают ваш вывод, превращая его в безопасный текст, вторые – доверяют содержимому и выводят HTML/скрипты напрямую.
Рекомендации:
- По умолчанию используйте
{{ $variable }}
. В 90% случаев это то, что вам нужно для корректного и безопасного отображения данных. - Применяйте
{!! $variable !!}
только когда необходимо показать HTML. Убедитесь в надежности источника данных. Если есть сомнения – лучше не использовать raw-вывод. - Думайте о том, кто сформировал данные. Если это пользователь или внешняя система – экранируйте без раздумий. Если это разработчик или система управления контентом с ограничениями – можно рассмотреть raw, но с осторожностью.
- Начинающим разработчикам: придерживайтесь принципа "не доверяй никому (данным)". Blade уже выбрал безопасный подход по умолчанию, следуйте ему. Опытным разработчикам: не пренебрегайте этими мерами – даже с большими знаниями важно не допускать оплошностей в мелочах.
- Всегда тестируйте, что отображается на странице. Если должны появиться специальные символы или теги, убедитесь, что они либо правильно экранированы, либо, если должны работать как HTML, что вы используете для них сырой вывод и они не содержат ничего лишнего.
Blade – ваш помощник в создании чистых и безопасных шаблонов. Пользуйтесь {{ }}
и {!! !!}
по назначению, и ваши Laravel-приложения будут радовать и пользователей, и разработчиков читаемым кодом и защищенностью.
Была статья полезной: