Layouts

Com organitzar les vistes amb layouts a Blade: layouts amb components i layouts clàssics.

Per què necessites layouts?#

A qualsevol aplicació web, la majoria de pàgines comparteixen elements comuns: el header, la navegació, el footer, els scripts i els estils CSS. Sense layouts, hauries de repetir tot aquest HTML a cada vista, cosa que faria el manteniment impossible. Els layouts permeten definir l'estructura comuna una sola vegada i reutilitzar-la a totes les pàgines.

Layouts amb components (recomanat)#

La manera recomanada de crear layouts a Laravel és amb components Blade. El layout és simplement un component que rep el contingut de cada pàgina a través del $slot:

{{-- resources/views/components/layout.blade.php --}}
<!DOCTYPE html>
<html lang="ca">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{ $title ?? 'Laravel Andorra' }}</title>
    @vite(['resources/css/app.css', 'resources/js/app.js'])
    {{ $head ?? '' }}
</head>
<body class="min-h-screen bg-gray-100">
    <nav class="bg-white shadow">
        <div class="max-w-7xl mx-auto px-4">
            <a href="/">Inici</a>
            <a href="/articles">Articles</a>
            @auth
                <a href="/dashboard">Dashboard</a>
            @endauth
        </div>
    </nav>
 
    <main class="max-w-7xl mx-auto px-4 py-8">
        {{ $slot }}
    </main>
 
    <footer class="bg-gray-800 text-white py-6">
        <div class="max-w-7xl mx-auto px-4">
            <p>&copy; {{ date('Y') }} Laravel Andorra</p>
        </div>
    </footer>
 
    {{ $scripts ?? '' }}
</body>
</html>

Per utilitzar el layout, simplement envolta el contingut de la teva vista amb el component:

{{-- resources/views/home.blade.php --}}
<x-layout>
    <x-slot:title>Pàgina d'inici</x-slot:title>
 
    <h1 class="text-3xl font-bold mb-4">Benvingut!</h1>
    <p>Aquesta és la pàgina principal de l'aplicació.</p>
</x-layout>

El contingut entre les etiquetes <x-layout> va al $slot del layout. El slot amb nom title personalitza el títol de la pàgina. Si no el passes, s'utilitza el valor per defecte 'Laravel Andorra'.

Layouts amb slots opcionals#

L'exemple anterior inclou slots opcionals com $head i $scripts que permeten a cada pàgina afegir contingut addicional al <head> o abans del tancament del <body>:

<x-layout>
    <x-slot:title>Dashboard</x-slot:title>
 
    <x-slot:head>
        <link rel="stylesheet" href="{{ asset('css/dashboard.css') }}">
    </x-slot:head>
 
    <h1>Dashboard</h1>
    <div id="chart"></div>
 
    <x-slot:scripts>
        <script src="{{ asset('js/chart.js') }}"></script>
    </x-slot:scripts>
</x-layout>

Múltiples layouts#

Pots tenir diversos layouts per a parts diferents de l'aplicació. Per exemple, un layout per a la part pública, un per al panell d'administració i un per a les pàgines d'autenticació:

{{-- Pàgina pública --}}
<x-layout>
    <h1>Benvingut</h1>
</x-layout>
 
{{-- Panell d'administració --}}
<x-admin-layout>
    <h1>Dashboard</h1>
</x-admin-layout>
 
{{-- Pàgina de login --}}
<x-auth-layout>
    <h1>Inicia sessió</h1>
</x-auth-layout>

Layouts clàssics amb @extends#

L'enfocament clàssic utilitza les directives @extends, @section i @yield. Tot i que els layouts amb components són la manera recomanada, entendre el sistema clàssic és important perquè molts projectes existents l'utilitzen.

Primer, defineixes el layout amb @yield als llocs on cada pàgina posarà el seu contingut:

{{-- resources/views/layouts/app.blade.php --}}
<!DOCTYPE html>
<html lang="ca">
<head>
    <meta charset="UTF-8">
    <title>@yield('title', 'Laravel Andorra')</title>
    @vite(['resources/css/app.css', 'resources/js/app.js'])
    @yield('styles')
</head>
<body>
    <nav>
        @include('partials.nav')
    </nav>
 
    <main class="container">
        @yield('content')
    </main>
 
    <footer>
        @include('partials.footer')
    </footer>
 
    @yield('scripts')
</body>
</html>

Després, les vistes filles utilitzen @extends per heretar el layout i @section per omplir els blocs:

{{-- resources/views/users/index.blade.php --}}
@extends('layouts.app')
 
@section('title', 'Llista d\'usuaris')
 
@section('content')
    <h1>Usuaris</h1>
 
    @forelse($users as $user)
        <div class="card">
            <h3>{{ $user->name }}</h3>
            <p>{{ $user->email }}</p>
        </div>
    @empty
        <p>No hi ha usuaris registrats.</p>
    @endforelse
 
    {{ $users->links() }}
@endsection
 
@section('scripts')
    <script src="{{ asset('js/users.js') }}"></script>
@endsection

La directiva @section amb un segon paràmetre (@section('title', 'Llista d\'usuaris')) estableix un valor curt. Per a blocs de contingut més llargs, utilitza @section amb @endsection.

@parent#

Si el layout defineix contingut per defecte a un bloc i la vista filla vol afegir-hi contingut en lloc de substituir-lo, pot fer servir @parent:

{{-- Layout --}}
@section('sidebar')
    <nav>Navegació per defecte</nav>
@show
 
{{-- Vista filla --}}
@section('sidebar')
    @parent
    <nav>Navegació addicional</nav>
@endsection

La directiva @parent insereix el contingut del layout al lloc on s'escriu, permetent estendre el bloc en lloc de sobreescriure'l completament.

Organitzar vistes#

A mesura que el projecte creix, és important organitzar les vistes en subdirectoris que reflecteixin l'estructura de l'aplicació:

resources/views/
├── components/
│   ├── layout.blade.php
│   ├── admin-layout.blade.php
│   ├── alert.blade.php
│   ├── button.blade.php
│   └── form/
│       ├── input.blade.php
│       └── select.blade.php
├── partials/
│   ├── nav.blade.php
│   └── footer.blade.php
├── users/
│   ├── index.blade.php
│   ├── show.blade.php
│   └── edit.blade.php
├── articles/
│   ├── index.blade.php
│   └── show.blade.php
└── home.blade.php

Els components van a components/, les vistes parcials reutilitzables a partials/, i les vistes de cada recurs en el seu propi directori. Per accedir a qualsevol vista, utilitza notació de punt: view('users.index') correspon a resources/views/users/index.blade.php.