Blade: een variabele definiëren en HTML veilig tonen

Blade: een variabele definiëren en HTML veilig tonen
Kort antwoord

Declareer in een Blade-view een variabele met @php $nom = '…'; @endphp, of geef hem door vanuit de controller met view('vue', compact('nom')). Om hem te tonen escapet {{ $nom }} de HTML, terwijl {!! $nom !!} hem ongewijzigd invoegt. Gebruik die tweede vorm alleen op vertrouwde inhoud: daar ontstaan de XSS-lekken.

Twee behoeften komen in een Blade-view steeds terug: er een variabele in declareren, en beslissen of de inhoud geëscaped moet worden of ongewijzigd doorgegeven. Dat tweede is geen comfortkwestie, het is precies het punt waarop je een XSS-lek introduceert.

Gepubliceerd in het traject Webdevelopment. Deze gids behandelt beide: een variabele in de view krijgen, er ter plaatse een declareren, en met kennis van zaken kiezen tussen {{ }} en {!! !!}. De voorbeelden zijn uitgevoerd op Laravel 13.30.1 met PHP 8.4.25.

Een variabele doorgeven vanuit de controller

Dat is de normale weg, en de weg die de voorkeur verdient: de view toont, de controller beslist. Het tweede argument van view() is een associatieve array waarvan elke sleutel een variabele wordt.

app/Http/Controllers/DashboardController.php
return view('dashboard', ['name' => 'Gekko']);
resources/views/dashboard.blade.php
<p>Bienvenue {{ $name }} !</p>

Voor het tonen van een datum uit een model, zie het werken met datums via Carbon.

Staan meerdere waarden al in PHP-variabelen, dan voorkomt compact() dat je de namen herhaalt:

php
$name    = 'Gekko';
$reseau  = 'gekkode';

return view('dashboard', compact('name', 'reseau'));

Met with() voeg je er onderweg nog een toe, wat handig is wanneer de waarde pas op het laatste moment wordt berekend:

php
return view('dashboard', compact('name'))->with('extra', 'valeur ajoutée');

Kan een variabele ontbreken, geef hem dan een terugvalwaarde in de view in plaats van er een conditie omheen te bouwen:

php
{{ $inconnu ?? 'valeur par défaut' }}

Een variabele rechtstreeks in de view declareren

Wanneer de waarde alleen voor de weergave dient, declareer je hem ter plaatse met de directive @php:

resources/views/dashboard.blade.php
@php
    $nom = 'Gekko';
    $classe = $task->active ? 'is-active' : 'is-done';
@endphp

<p class="{{ $classe }}">Bonjour {{ $nom }}</p>

Klassieke PHP-tags werken ook, maar @php blijft leesbaarder en sluit beter aan bij de rest van het template.

Twee directives dekken aangrenzende gevallen zonder dat er een variabele aan te pas komt. @class bouwt een class-attribuut op uit condities:

php
<div @class(['actif' => $task->active, 'masque' => $task->hidden])></div>

<!-- rendu quand active vaut true et hidden false -->
<div class="actif"></div>

En @once garandeert dat een blok maar één keer wordt gerenderd, ook als de view meerdere keren in de pagina wordt opgenomen:

php
@once
    <script src="/js/carte.js" defer></script>
@endonce
Waar het redelijke ophoudt

@php is prima voor een weergavewaarde. Zodra het om een databasequery, een businessberekening of een transformatielus gaat, hoort de code thuis in de controller, in een Blade-component of in een accessor van het model. Een view die de database bevraagt, veroorzaakt N+1-queries die vanuit de controller onzichtbaar zijn.

HTML tonen: {{ }} tegenover {!! !!}

Blade compileert {{ $variable }} naar een aanroep van de functie e(), die de speciale tekens escapet. Dat is zichtbaar in de gecompileerde view, onder storage/framework/views:

php
<?php echo e($nom); ?>

Gevolg: bevat de variabele tags, dan verschijnen die voluit op het scherm in plaats van geïnterpreteerd te worden.

php
@php $html = '<strong>gras</strong>'; @endphp

{{ $html }}     {{-- affiche : &lt;strong&gt;gras&lt;/strong&gt; --}}
{!! $html !!}   {{-- affiche : gras, en gras --}}

De syntaxis {!! !!} voegt de waarde zonder enige bewerking in. Dat heb je nodig om een in HTML geschreven artikeltekst te tonen, en het is tegelijk de voordeur voor een script-injectie zodra de waarde van een gebruiker komt.

De regel die je niet omzeilt

Gebruik {!! !!} alleen op HTML waarvan je de herkomst kent, of die vooraf is opgeschoond. Met de waarde <script>alert(1)</script> toont {{ }} de tekst, terwijl {!! !!} het script in de browser van de bezoeker uitvoert. Beide gedragingen zijn nagegaan.

Voor inhoud die uit een formulier komt, dat je uiteraard tegen geautomatiseerde inzendingen hebt beschermd, schoon je op voordat je toont. Een bibliotheek als HTML Purifier past een whitelist van tags toe, kan dat niet, sla dan Markdown op en zet die om bij het renderen, zodat jij bepaalt welke tags eruit komen.

De nuttige bijzondere gevallen

Om data door te geven aan JavaScript produceert @json een geldig en geëscaped literal:

php
<script>
    const config = @json(['id' => $task->id, 'titre' => $task->title]);
</script>

Om accolades te tonen zonder dat Blade ze interpreteert, bijvoorbeeld in een template dat voor een JavaScript-framework bedoeld is, schakelt @verbatim het hele blok uit:

php
@verbatim
    <div id="app">{{ message }}</div>
@endverbatim

Voor één enkele expressie volstaat het er een apenstaartje voor te zetten: @{{ message }}.

Roep e() niet aan binnen dubbele accolades

{{ e($valeur) }} escapet twee keer: <b> wordt &amp;lt;b&amp;gt; en verschijnt letterlijk op het scherm. {{ }} doet het al. De functie e() is alleen nuttig buiten Blade, of binnen een {!! !!} op een specifiek stuk.

Veelgemaakte fouten

{!! !!} op een waarde van een gebruiker De string <script>alert(1)</script> wordt echt uitgevoerd in de browser van de bezoeker. Schoon de HTML eerst op, of sla Markdown op.
{{ e($valeur) }} escapet twee keer De dubbele accolades roepen e() al aan. Het resultaat toont de entiteiten op het scherm in plaats van de tekst.
Een databasequery in @php De view zet queries in gang die de controller niet ziet, wat onzichtbare N+1 oplevert. Verplaats de logica naar de controller of naar een component.
De terugval op een optionele variabele vergeten {{ $var ?? 'défaut' }} voorkomt een fout als de controller hem niet in alle gevallen heeft doorgegeven.

BladeLaravelPHP

Damien Flandrin Webdeveloper sinds 2010, maker van Gekkode en Email Impact. Elk artikel wordt vóór publicatie getest op een echt project. Contact
Nieuwsbrief

Nieuwe tests, tutorials en projecten, per e-mail.

Reproduceerbare tests, geversioneerde code, gedateerde resultaten. Nooit spam.