Blade: sintaxi bàsica

La sintaxi bàsica de Blade: mostrar dades, directives condicionals, bucles i comentaris.

Retornar una vista#

Abans d'entrar en la sintaxi de Blade, és important entendre com es retornen les vistes des d'un controlador o ruta. El helper view() cerca el fitxer corresponent dins de resources/views/ utilitzant notació de punt per als subdirectoris:

// Retorna resources/views/welcome.blade.php
return view('welcome');
 
// Retorna resources/views/users/index.blade.php
return view('users.index');
 
// Passar dades a la vista
return view('users.show', [
    'user' => $user,
    'posts' => $user->posts,
]);
 
// Amb compact() per passar variables amb el mateix nom
return view('users.show', compact('user', 'posts'));

Les dades passades a la vista estan disponibles com a variables dins del fitxer Blade.

Mostrar dades#

Blade utilitza dobles claus {{ }} per mostrar el contingut d'una variable. Totes les dades que es mostren amb dobles claus s'escapen automàticament amb htmlspecialchars() per prevenir atacs XSS:

<h1>{{ $title }}</h1>
<p>Benvingut, {{ $user->name }}!</p>
<span>Tens {{ $notifications->count() }} notificacions.</span>

Pots executar qualsevol expressió PHP dins de les dobles claus, no només variables:

<p>La data actual és {{ now()->format('d/m/Y') }}</p>
<p>{{ $users->isEmpty() ? 'No hi ha usuaris' : $users->count() . ' usuaris' }}</p>

Si necessites mostrar HTML sense escapar (per exemple, contingut d'un editor WYSIWYG), utilitza {!! !!}. Fes-ho només amb dades de confiança, ja que no s'aplica cap protecció contra XSS:

{{-- Escapada automàticament (segur): &lt;script&gt; no s'executarà --}}
<div>{{ $userInput }}</div>
 
{{-- Sense escapar (perill!): el HTML es renderitza tal qual --}}
<div>{!! $trustedHtml !!}</div>

Mostrar dades amb valors per defecte#

Quan una variable pot no existir, Blade ofereix l'operador ?? i la directiva @verbatim per evitar errors:

{{-- Si $name no existeix, mostra 'Convidat' --}}
<p>Hola, {{ $name ?? 'Convidat' }}</p>

Si treballes amb un framework JavaScript que també utilitza dobles claus (com Vue.js), pots fer servir @ per indicar a Blade que no processi l'expressió:

{{-- Blade ignora aquesta expressió --}}
<p>@{{ vueVariable }}</p>

Directives condicionals#

Blade proporciona directives que fan que les condicions siguin netes i llegibles. La directiva @if funciona exactament com el if de PHP, però sense necessitat d'obrir i tancar etiquetes PHP:

@if($users->count() > 0)
    <p>Hi ha {{ $users->count() }} usuaris registrats.</p>
@elseif($users->count() === 0)
    <p>Encara no hi ha cap usuari registrat.</p>
@else
    <p>Error al carregar els usuaris.</p>
@endif

La directiva @unless és l'invers de @if, i resulta més llegible en certs contextos:

@unless($user->isAdmin())
    <p>No tens permisos d'administrador.</p>
@endunless

Per comprovar si una variable existeix o si és buida, utilitza @isset i @empty:

@isset($record)
    <p>El registre existeix: {{ $record->name }}</p>
@endisset
 
@empty($records)
    <p>No hi ha registres per mostrar.</p>
@endempty

Directives d'autenticació#

Laravel inclou directives específiques per comprovar l'estat d'autenticació de l'usuari. Això evita escriure condicions manuals amb Auth::check():

@auth
    <p>Benvingut, {{ auth()->user()->name }}!</p>
    <form method="POST" action="/logout">
        @csrf
        <button type="submit">Tanca sessió</button>
    </form>
@endauth
 
@guest
    <a href="/login">Inicia sessió</a>
    <a href="/register">Registra't</a>
@endguest

Directives d'autorització#

Les directives @can i @cannot permeten mostrar o ocultar contingut segons els permisos de l'usuari, basant-se en les polítiques d'autorització:

@can('update', $article)
    <a href="{{ route('articles.edit', $article) }}">Editar article</a>
@endcan
 
@cannot('delete', $article)
    <p>No tens permisos per eliminar aquest article.</p>
@endcannot

Bucles#

Blade ofereix directives per a tots els tipus de bucle de PHP. La directiva @foreach és la més habitual:

@foreach($users as $user)
    <div class="user-card">
        <h3>{{ $user->name }}</h3>
        <p>{{ $user->email }}</p>
    </div>
@endforeach

La directiva @forelse és especialment útil perquè combina un foreach amb un missatge per quan la col·lecció és buida, cosa que evita un @if separat:

@forelse($articles as $article)
    <article>
        <h2>{{ $article->title }}</h2>
        <p>{{ $article->excerpt }}</p>
    </article>
@empty
    <p>Encara no hi ha cap article publicat.</p>
@endforelse

La variable $loop#

Dins de qualsevol bucle Blade, tens accés a la variable especial $loop, que proporciona informació útil sobre la iteració actual:

@foreach($items as $item)
    <div class="item {{ $loop->even ? 'bg-gray-50' : '' }}">
        <span>{{ $loop->iteration }}.</span>
        <span>{{ $item->name }}</span>
 
        @if($loop->first)
            <span class="badge">Primer</span>
        @endif
 
        @if($loop->last)
            <span class="badge">Últim</span>
        @endif
    </div>
@endforeach

La variable $loop ofereix les propietats següents: $loop->index (comença a 0), $loop->iteration (comença a 1), $loop->remaining (iteracions restants), $loop->count (total d'elements), $loop->first i $loop->last (si és el primer o últim element), $loop->even i $loop->odd (si la iteració és parell o senar), i $loop->depth (nivell de nidificació en bucles niuats).

En bucles niuats, pots accedir al $loop del bucle pare amb $loop->parent:

@foreach($categories as $category)
    <h2>{{ $category->name }}</h2>
    @foreach($category->products as $product)
        <p>{{ $product->name }} (Categoria {{ $loop->parent->iteration }})</p>
    @endforeach
@endforeach

@for i @while#

Per a bucles numèrics o condicionals, pots fer servir @for i @while:

@for($i = 0; $i < 10; $i++)
    <p>Iteració {{ $i }}</p>
@endfor
 
@while($condition)
    <p>Repetint...</p>
@endwhile

Incloure subvistes#

La directiva @include permet incloure una vista dins d'una altra. La vista inclosa hereta totes les variables disponibles a la vista pare:

<div class="page">
    @include('partials.header')
 
    <main>
        {{ $slot }}
    </main>
 
    @include('partials.footer')
</div>

Pots passar dades addicionals a la vista inclosa amb un segon paràmetre:

@include('partials.alert', ['type' => 'success', 'message' => 'Operació completada!'])

Si no estàs segur de si la vista existeix, utilitza @includeIf per evitar un error:

@includeIf('partials.analytics')

La directiva @includeWhen inclou la vista només si es compleix una condició:

@includeWhen($user->isAdmin(), 'partials.admin-panel')

Per incloure una vista per a cada element d'una col·lecció, utilitza @each:

@each('partials.user-card', $users, 'user', 'partials.no-users')

Això renderitza partials.user-card per a cada element de $users, passant cada element com a $user. Si la col·lecció és buida, renderitza partials.no-users.

Comentaris#

Els comentaris Blade no apareixen al HTML generat, a diferència dels comentaris HTML que sí que són visibles al codi font de la pàgina:

{{-- Això és un comentari Blade: no apareixerà al HTML --}}
 
<!-- Això és un comentari HTML: sí que apareixerà al codi font -->

Directiva @csrf i @method#

Quan crees formularis, Laravel requereix un token CSRF per protegir-te d'atacs. La directiva @csrf genera automàticament un camp ocult amb el token:

<form method="POST" action="{{ route('users.store') }}">
    @csrf
 
    <input type="text" name="name">
    <button type="submit">Crear</button>
</form>

Com que els formularis HTML només suporten GET i POST, per a accions PUT, PATCH o DELETE necessites la directiva @method:

<form method="POST" action="{{ route('users.update', $user) }}">
    @csrf
    @method('PUT')
 
    <input type="text" name="name" value="{{ $user->name }}">
    <button type="submit">Actualitzar</button>
</form>
 
<form method="POST" action="{{ route('users.destroy', $user) }}">
    @csrf
    @method('DELETE')
 
    <button type="submit">Eliminar</button>
</form>

Mostrar errors de validació#

Quan una validació falla, Laravel redirigeix l'usuari al formulari amb els errors a la sessió. Blade proporciona la directiva @error per mostrar-los fàcilment:

<form method="POST" action="{{ route('users.store') }}">
    @csrf
 
    <div>
        <label for="name">Nom</label>
        <input type="text" name="name" value="{{ old('name') }}"
               class="@error('name') border-red-500 @enderror">
        @error('name')
            <p class="text-red-500 text-sm">{{ $message }}</p>
        @enderror
    </div>
 
    <div>
        <label for="email">Email</label>
        <input type="email" name="email" value="{{ old('email') }}"
               class="@error('email') border-red-500 @enderror">
        @error('email')
            <p class="text-red-500 text-sm">{{ $message }}</p>
        @enderror
    </div>
 
    <button type="submit">Crear</button>
</form>

Fixa't com s'utilitza old('name') per recuperar el valor que l'usuari havia escrit, i @error per mostrar el missatge d'error i afegir classes CSS al camp amb error.