
In a Blade view, declare a variable with @php $nom = '…'; @endphp, or pass it in from the controller with view('vue', compact('nom')). To display it, {{ $nom }} escapes the HTML and {!! $nom !!} inserts it as is. Only use the second form on trusted content: that is where XSS holes are created.
Two needs come up constantly in a Blade view: declaring a variable there, and deciding whether its content should be escaped or rendered as is. The second one is not a matter of comfort, it is the exact spot where an XSS hole gets introduced.
Published in the Web development track. This guide covers both: getting a variable into the view, declaring one on the spot, and choosing between {{ }} and {!! !!} with your eyes open. The examples were run on Laravel 13.30.1 with PHP 8.4.25.
Passing a variable from the controller
This is the normal route, and the one to favour: the view displays, the controller decides. The second argument to view() is an associative array whose keys each become a variable.
return view('dashboard', ['name' => 'Gekko']);<p>Bienvenue {{ $name }} !</p>To display a date coming from a model, see handling dates with Carbon.
For several values that already live in PHP variables, compact() saves repeating the names:
$name = 'Gekko';
$reseau = 'gekkode';
return view('dashboard', compact('name', 'reseau'));with() lets you add one along the way, which is handy when the value is computed at the last moment:
return view('dashboard', compact('name'))->with('extra', 'valeur ajoutée');If a variable may be missing, give it a fallback value in the view rather than adding a condition:
{{ $inconnu ?? 'valeur par défaut' }}Declaring a variable directly in the view
When the value only exists for display, the @php directive lets you declare it on the spot:
@php
$nom = 'Gekko';
$classe = $task->active ? 'is-active' : 'is-done';
@endphp
<p class="{{ $classe }}">Bonjour {{ $nom }}</p>Plain PHP tags work too, but @php reads better and stays consistent with the rest of the template.
Two directives cover the neighbouring cases without going through a variable at all. @class builds a class attribute from a set of conditions:
<div @class(['actif' => $task->active, 'masque' => $task->hidden])></div>
<!-- rendu quand active vaut true et hidden false -->
<div class="actif"></div>And @once guarantees that a block is rendered only once, even if the view is included several times on the page:
@once
<script src="/js/carte.js" defer></script>
@endonce@php is fine for a display value. As soon as a database query, a business calculation or a transformation loop is involved, the code belongs in the controller, in a Blade component or in a model accessor. A view that queries the database generates N+1 queries that are invisible from the controller.
Outputting HTML: {{ }} versus {!! !!}
Blade compiles {{ $variable }} into a call to the e() function, which escapes special characters. You can see it in the compiled view, under storage/framework/views:
<?php echo e($nom); ?>The consequence: if the variable contains tags, they are printed as literal text instead of being interpreted.
@php $html = '<strong>gras</strong>'; @endphp
{{ $html }} {{-- affiche : <strong>gras</strong> --}}
{!! $html !!} {{-- affiche : gras, en gras --}}The {!! !!} syntax inserts the value with no transformation at all. That is what you want for an article body written in HTML, and it is also the way in for a script injection when the value comes from a user.
Only use {!! !!} on HTML whose origin you control, or that has been sanitised beforehand. With the value <script>alert(1)</script>, {{ }} prints the text while {!! !!} runs the script in the visitor’s browser. Both behaviours were verified.
For content coming from a form, which you will have taken care to protect against automated submissions, sanitise before you display. A library such as HTML Purifier applies an allowlist of tags, failing that, store Markdown and convert it at render time, which leaves you in control of the tags produced.
The special cases worth knowing
To pass data to JavaScript, @json produces a valid, escaped literal:
<script>
const config = @json(['id' => $task->id, 'titre' => $task->title]);
</script>To print braces without Blade interpreting them, in a template meant for a JavaScript framework for instance, @verbatim neutralises the whole block:
@verbatim
<div id="app">{{ message }}</div>
@endverbatimFor a single expression, prefixing it with an at sign is enough: @{{ message }}.
{{ e($valeur) }} escapes twice: <b> becomes &lt;b&gt; and shows up literally on screen. {{ }} already does it. The e() function is only useful outside Blade, or inside a {!! !!} on one specific portion.
Common errors
<script>alert(1)</script> really does run in the visitor’s browser. Sanitise the HTML first, or store Markdown.e(). The result shows the entities on screen instead of the text.{{ $var ?? 'défaut' }} avoids an error when the controller does not pass it in every case.

