Blade

Introduzione

Blade è il motore di template semplice ma potente incluso in Laravel. A differenza di alcuni motori di template PHP, Blade non ti limita nell’uso del codice PHP normale nei tuoi template. In realtà, tutti i template Blade vengono compilati in codice PHP semplice e memorizzati nella cache fino a quando non vengono modificati, il che significa che Blade non aggiunge ulteriore carico alla tua applicazione. I file dei template Blade utilizzano l’estensione .blade.php e sono generalmente archiviati nella directory resources/views.

Le viste Blade possono essere restituite dalle route o dai controller utilizzando l’helper globale view. Naturalmente, come menzionato nella documentazione su views, i dati possono essere passati alla vista Blade usando il secondo argomento dell’helper view:

    Route::get('/', function () {
        return view('greeting', ['name' => 'Finn']);
    });

Potenziare Blade con Livewire

Vuoi elevare i tuoi template Blade e creare interfacce dinamiche con facilità? Dai un’occhiata a Laravel Livewire. Livewire ti permette di scrivere componenti Blade arricchiti con funzionalità dinamiche che solitamente sarebbero possibili solo con framework frontend come React o Vue, offrendo un ottimo modo per costruire frontend moderni e reattivi senza le complessità, il rendering lato client o le fasi di build di molti framework JavaScript.

Visualizzazione dei Dati

Puoi visualizzare i dati passati alle tue viste Blade racchiudendo la variabile tra parentesi graffe. Ad esempio, data la seguente route:

Route::get('/', function () {
    return view('welcome', ['name' => 'Samantha']);
});

Puoi mostrare il contenuto della variabile name in questo modo:

Ciao, {{ $name }}.

Le istruzioni di echo {{ }} di Blade sono automaticamente passate attraverso la funzione htmlspecialchars di PHP per prevenire attacchi XSS.

Non sei limitato a mostrare il contenuto delle variabili passate alla vista. Puoi anche fare echo dei risultati di qualsiasi funzione PHP. In effetti, puoi inserire qualsiasi codice PHP desideri all’interno di un’istruzione echo di Blade:

Il timestamp UNIX corrente è {{ time() }}.

Codifica delle entità HTML

Per impostazione predefinita, Blade (e la funzione e di Laravel) esegue la doppia codifica delle entità HTML. Se desideri disabilitare la doppia codifica, chiama il metodo Blade::withoutDoubleEncoding dal metodo boot del tuo AppServiceProvider:

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        Blade::withoutDoubleEncoding();
    }
}

Visualizzazione di dati non escaped

Per impostazione predefinita, le istruzioni Blade {{ }} vengono automaticamente passate attraverso la funzione htmlspecialchars di PHP per prevenire attacchi XSS. Se non vuoi che i tuoi dati vengano sottoposti ad escape, puoi usare la seguente sintassi:

Hello, {!! $name !!}.

Fai molta attenzione quando mostri contenuti forniti dagli utenti della tua applicazione. In genere dovresti usare la sintassi con doppie parentesi graffe e fare escape dei dati per prevenire attacchi XSS quando mostri dati forniti dagli utenti.

Blade e Framework JavaScript

Poiché molti framework JavaScript utilizzano le parentesi graffe per indicare che un’espressione deve essere visualizzata nel browser, puoi usare il simbolo @ per informare il motore di rendering di Blade che un’espressione deve rimanere invariata. Ad esempio:

<h1>Laravel</h1>

Hello, @{{ name }}.

In questo esempio, il simbolo @ verrà rimosso da Blade; tuttavia, l’espressione {{ name }} rimarrà intatta nel motore Blade, permettendo al tuo framework JavaScript di renderizzarla.

Il simbolo @ può essere usato anche per eseguire l’escape delle direttive di Blade:

{{-- Template Blade --}}
@@if()

<!-- Output HTML -->
@if()

Visualizzazione JSON

A volte potresti passare un array alla tua view con l’intenzione di renderizzarlo come JSON per inizializzare una variabile JavaScript. Ad esempio:

<script>
    var app = <?php echo json_encode($array); ?>;
</script>

Tuttavia, invece di chiamare manualmente json_encode, puoi usare il metodo direttiva Illuminate\Support\Js::from. Il metodo from accetta gli stessi argomenti della funzione json_encode di PHP; tuttavia, garantirà che il JSON risultante sia correttamente sottoposto ad escape per l’inclusione all’interno delle virgolette HTML. Il metodo from restituirà una stringa con un’istruzione JavaScript JSON.parse che convertirà l’oggetto o l’array fornito in un oggetto JavaScript valido:

<script>
    var app = {{ Illuminate\Support\Js::from($array) }};
</script>

Le versioni più recenti di un’app Laravel includono un facade Js, che fornisce un accesso comodo a questa funzionalità all’interno delle tue template Blade:

<script>
    var app = {{ Js::from($array) }};
</script>

Dovresti usare il metodo Js::from solo per rendere variabili esistenti come JSON. Il template Blade si basa su espressioni regolari e tentativi di passare un’espressione complessa alla direttiva potrebbero causare errori inaspettati.

La direttiva @verbatim

Se visualizzi variabili JavaScript in parti rilevanti del tuo template, puoi racchiudere l’HTML nella direttiva @verbatim in modo da non dover aggiungere un simbolo @ davanti a ogni dichiarazione echo di Blade:

@verbatim
    <div class="container">
        Hello, {{ name }}.
    </div>
@endverbatim

Blade Directives

Oltre all’ereditarietà dei template e alla visualizzazione dei dati, Blade offre anche scorciatoie utili per le comuni strutture di controllo PHP, come le istruzioni condizionali e i cicli. Queste scorciatoie permettono di gestire le strutture di controllo PHP in modo pulito e conciso, rimanendo familiari ai loro equivalenti in PHP.

Istruzioni If

Puoi creare istruzioni if usando le direttive @if, @elseif, @else e @endif. Queste direttive funzionano come le loro controparti PHP:

@if (count($records) === 1)
    I have one record!
@elseif (count($records) > 1)
    I have multiple records!
@else
    I don't have any records!
@endif

Per comodità, Blade offre anche una direttiva @unless:

@unless (Auth::check())
    You are not signed in.
@endunless

Oltre alle direttive condizionali già menzionate, le direttive @isset e @empty possono essere utilizzate come scorciatoie pratiche per le rispettive funzioni PHP:

@isset($records)
    // $records è definito e non è null...
@endisset

@empty($records)
    // $records è "vuoto"...
@endempty

Direttive di Autenticazione

Le direttive @auth e @guest possono essere usate per verificare rapidamente se l’utente corrente è autenticato oppure è un ospite:

@auth
    // L'utente è autenticato...
@endauth

@guest
    // L'utente non è autenticato...
@endguest

Se necessario, puoi specificare la guardia di autenticazione che deve essere controllata quando usi le direttive @auth e @guest:

@auth('admin')
    // L'utente è autenticato...
@endauth

@guest('admin')
    // L'utente non è autenticato...
@endguest

Direttive di Ambiente

Puoi verificare se l’applicazione è in esecuzione nell’ambiente di produzione usando la direttiva @production:

@production
    // Contenuto specifico per la produzione...
@endproduction

Oppure, puoi determinare se l’applicazione è in esecuzione in un ambiente specifico usando la direttiva @env:

@env('staging')
    // L'applicazione è in esecuzione in "staging"...
@endenv

@env(['staging', 'production'])
    // L'applicazione è in esecuzione in "staging" o "production"...
@endenv

Direttive per le Sezioni

Puoi verificare se una sezione nell’ereditarietà del template contiene contenuto usando la direttiva @hasSection:

@hasSection('navigation')
    <div class="pull-right">
        @yield('navigation')
    </div>

    <div class="clearfix"></div>
@endif

Puoi usare la direttiva sectionMissing per verificare se una sezione non ha contenuto:

@sectionMissing('navigation')
    <div class="pull-right">
        @include('default-navigation')
    </div>
@endif

Direttive della Sessione

La direttiva @session può essere utilizzata per verificare se esiste un valore di sessione. Se il valore della sessione esiste, il contenuto del template all’interno delle direttive @session e @endsession verrà valutato. All’interno del contenuto della direttiva @session, puoi utilizzare la variabile $value per mostrare il valore della sessione:

@session('status')
    <div class="p-4 bg-green-100">
        {{ $value }}
    </div>
@endsession

Istruzioni Switch

Le istruzioni switch possono essere create usando le direttive @switch, @case, @break, @default e @endswitch:

@switch($i)
    @case(1)
        Primo caso...
        @break

    @case(2)
        Secondo caso...
        @break

    @default
        Caso predefinito...
@endswitch

Cicli

Oltre alle istruzioni condizionali, Blade offre direttive semplici per lavorare con le strutture di ciclo di PHP. Anche queste direttive funzionano come i loro equivalenti in PHP:

@for ($i = 0; $i < 10; $i++)
    The current value is {{ $i }}
@endfor

@foreach ($users as $user)
    <p>This is user {{ $user->id }}</p>
@endforeach

@forelse ($users as $user)
    <li>{{ $user->name }}</li>
@empty
    <p>No users</p>
@endforelse

@while (true)
    <p>I'm looping forever.</p>
@endwhile

Durante un ciclo foreach, puoi usare la variabile loop per ottenere informazioni utili sul ciclo, come se sei nella prima o nell’ultima iterazione.

Quando usi i cicli, puoi anche saltare l’iterazione corrente o terminare il ciclo usando le direttive @continue e @break:

@foreach ($users as $user)
    @if ($user->type == 1)
        @continue
    @endif

    <li>{{ $user->name }}</li>

    @if ($user->number == 5)
        @break
    @endif
@endforeach

Puoi anche includere la condizione per continuare o interrompere direttamente nella dichiarazione della direttiva:

@foreach ($users as $user)
    @continue($user->type == 1)

    <li>{{ $user->name }}</li>

    @break($user->number == 5)
@endforeach

La Variabile Loop

Durante l’iterazione attraverso un ciclo foreach, sarà disponibile una variabile $loop all’interno del tuo ciclo. Questa variabile fornisce accesso a informazioni utili come l’indice corrente del ciclo e se questa è la prima o l’ultima iterazione del ciclo:

@foreach ($users as $user)
    @if ($loop->first)
        Questa è la prima iterazione.
    @endif

    @if ($loop->last)
        Questa è l'ultima iterazione.
    @endif

    <p>Questo è l'utente {{ $user->id }}</p>
@endforeach

Se ti trovi in un ciclo annidato, puoi accedere alla variabile $loop del ciclo padre tramite la proprietà parent:

@foreach ($users as $user)
    @foreach ($user->posts as $post)
        @if ($loop->parent->first)
            Questa è la prima iterazione del ciclo padre.
        @endif
    @endforeach
@endforeach

La variabile $loop contiene anche una varietà di altre proprietà utili:

Proprietà Descrizione
$loop->index L’indice dell’attuale iterazione del ciclo (inizia da 0).
$loop->iteration L’attuale iterazione del ciclo (inizia da 1).
$loop->remaining Le iterazioni rimanenti nel ciclo.
$loop->count Il numero totale di elementi nell’array iterato.
$loop->first Se questa è la prima iterazione del ciclo.
$loop->last Se questa è l’ultima iterazione del ciclo.
$loop->even Se questa è un’iterazione pari del ciclo.
$loop->odd Se questa è un’iterazione dispari del ciclo.
$loop->depth Il livello di annidamento del ciclo corrente.
$loop->parent Quando si è in un ciclo annidato, la variabile del ciclo padre.

Classi e Stili Condizionali

La direttiva @class compila condizionalmente una stringa di classi CSS. La direttiva accetta un array di classi dove la chiave dell’array contiene la classe o le classi che vuoi aggiungere, mentre il valore è un’espressione booleana. Se l’elemento dell’array ha una chiave numerica, sarà sempre incluso nell’elenco delle classi renderizzate:

@php
    $isActive = false;
    $hasError = true;
@endphp

<span @class([
    'p-4',
    'font-bold' => $isActive,
    'text-gray-500' => ! $isActive,
    'bg-red' => $hasError,
])></span>

<span class="p-4 text-gray-500 bg-red"></span>

Allo stesso modo, la direttiva @style può essere utilizzata per aggiungere condizionalmente stili CSS inline a un elemento HTML:

@php
    $isActive = true;
@endphp

<span @style([
    'background-color: red',
    'font-weight: bold' => $isActive,
])></span>

<span style="background-color: red; font-weight: bold;"></span>

Attributi Aggiuntivi

Per comodità, puoi usare la direttiva @checked per indicare facilmente se un input checkbox HTML è "checked". Questa direttiva stamperà checked se la condizione fornita è true:

<input
    type="checkbox"
    name="active"
    value="active"
    @checked(old('active', $user->active))
/>

Allo stesso modo, la direttiva @selected può essere usata per indicare se un’opzione select deve essere "selected":

<select name="version">
    @foreach ($product->versions as $version)
        <option value="{{ $version }}" @selected(old('version') == $version)>
            {{ $version }}
        </option>
    @endforeach
</select>

Inoltre, la direttiva @disabled può essere utilizzata per indicare se un elemento deve essere "disabled":

<button type="submit" @disabled($errors->isNotEmpty())>Submit</button>

Inoltre, la direttiva @readonly può essere usata per indicare se un elemento deve essere "readonly":

<input
    type="email"
    name="email"
    value="email@laravel.com"
    @readonly($user->isNotAdmin())
/>

In aggiunta, la direttiva @required può essere usata per indicare se un elemento deve essere "required":

<input
    type="text"
    name="title"
    value="title"
    @required($user->isAdmin())
/>

Inclusione di subview

Anche se puoi usare la direttiva @include, i componenti di Blade offrono funzionalità simili e diversi vantaggi rispetto alla direttiva @include, come il data e l’attribute binding.

La direttiva @include di Blade ti permette di includere una view Blade all’interno di un’altra view. Tutte le variabili disponibili nella view principale saranno disponibili anche nella view inclusa:

<div>
    @include('shared.errors')

    <form>
        <!-- Contenuto del Form -->
    </form>
</div>

Anche se la view inclusa erediterà tutti i dati disponibili nella view principale, puoi anche passare un array di dati aggiuntivi che devono essere disponibili nella view inclusa:

@include('view.name', ['status' => 'complete'])

Se tenti di usare @include con una view che non esiste, Laravel genererà un errore. Se desideri includere una view che potrebbe essere presente o meno, dovresti usare la direttiva @includeIf:

@includeIf('view.name', ['status' => 'complete'])

Se vuoi usare @include solo se una determinata espressione booleana risulta true o false, puoi usare le direttive @includeWhen e @includeUnless:

@includeWhen($boolean, 'view.name', ['status' => 'complete'])

@includeUnless($boolean, 'view.name', ['status' => 'complete'])

Per includere la prima view esistente da un dato array di views, puoi usare la direttiva includeFirst:

@includeFirst(['custom.admin', 'admin'], ['status' => 'complete'])

Dovresti evitare di usare le costanti __DIR__ e __FILE__ nelle tue view Blade, poiché si riferiranno alla posizione della view compilata e in cache.

Rendering delle View per Collezioni

Puoi combinare cicli e inclusioni in una sola riga con la direttiva @each di Blade:

@each('view.name', $jobs, 'job')

Il primo argomento della direttiva @each è la view da renderizzare per ogni elemento nell’array o nella collezione. Il secondo argomento è l’array o la collezione su cui iterare, mentre il terzo argomento è il nome della variabile che sarà assegnata all’iterazione corrente all’interno della view. Ad esempio, se stai iterando su un array di jobs, di solito vorrai accedere a ogni job come variabile job nella view. La chiave dell’array per l’iterazione corrente sarà disponibile come variabile key nella view.

Puoi anche passare un quarto argomento alla direttiva @each. Questo argomento determina la view che verrà renderizzata se l’array fornito è vuoto.

@each('view.name', $jobs, 'job', 'view.empty')

Le view renderizzate tramite @each non ereditano le variabili dalla view padre. Se la view figlia necessita di queste variabili, dovresti usare le direttive @foreach e @include invece.

La direttiva @once

La direttiva @once ti permette di definire una parte del template che verrà valutata solo una volta per ciclo di rendering. Questo può essere utile per inserire un determinato pezzo di JavaScript nell’header della pagina usando stacks. Ad esempio, se stai renderizzando un component all’interno di un ciclo, potresti voler inserire il JavaScript nell’header solo la prima volta che il componente viene renderizzato:

@once
    @push('scripts')
        <script>
            // Your custom JavaScript...
        </script>
    @endpush
@endonce

Poiché la direttiva @once è spesso utilizzata insieme alle direttive @push o @prepend, le direttive @pushOnce e @prependOnce sono disponibili per tua comodità:

@pushOnce('scripts')
    <script>
        // Your custom JavaScript...
    </script>
@endPushOnce

PHP "Vanilla"

In alcune situazioni, è utile incorporare codice PHP nelle tue viste. Puoi usare la direttiva Blade @php per eseguire un blocco di PHP semplice all’interno del tuo template:

@php
    $counter = 1;
@endphp

Oppure, se devi solo usare PHP per importare una classe, puoi usare la direttiva @use:

@use('App\Models\Flight')

Puoi fornire un secondo argomento alla direttiva @use per assegnare un alias alla classe importata:

@use('App\Models\Flight', 'FlightModel')

Commenti

Blade permette anche di definire commenti nelle tue viste. Tuttavia, a differenza dei commenti HTML, i commenti Blade non vengono inclusi nell’HTML restituito dalla tua applicazione:

{{-- Questo commento non sarà presente nell'HTML renderizzato --}}

Componenti

I componenti e gli slot offrono benefici simili a sezioni, layout e include; tuttavia, alcuni potrebbero trovare più facile comprendere il modello mentale di componenti e slot. Esistono due modi per scrivere i componenti: componenti basati su classi e componenti anonimi.

Per creare un componente basato su classe, puoi usare il comando Artisan make:component. Per mostrare come utilizzare i componenti, creeremo un semplice componente Alert. Il comando make:component posizionerà il componente nella directory app/View/Components:

php artisan make:component Alert

Il comando make:component creerà anche un template di view per il componente. La view sarà collocata nella directory resources/views/components. Quando scrivi componenti per la tua applicazione, i componenti vengono scoperti automaticamente nelle directory app/View/Components e resources/views/components, quindi solitamente non è necessaria una registrazione ulteriore.

Puoi anche creare componenti all’interno di sottocartelle:

php artisan make:component Forms/Input

Il comando sopra creerà un componente Input nella directory app/View/Components/Forms e la view sarà posizionata nella directory resources/views/components/forms.

Se vuoi creare un componente anonimo (un componente con solo un template Blade e senza classe), puoi usare l’opzione --view quando esegui il comando make:component:

php artisan make:component forms.input --view

Il comando sopra creerà un file Blade in resources/views/components/forms/input.blade.php che può essere utilizzato come componente tramite <x-forms.input />.

Registrazione Manuale dei Componenti del Package

Quando crei componenti per la tua applicazione, essi vengono scoperti automaticamente nelle directory app/View/Components e resources/views/components.

Tuttavia, se stai sviluppando un package che utilizza componenti Blade, dovrai registrare manualmente la classe del tuo componente e il suo alias del tag HTML. Di solito, dovresti registrare i tuoi componenti nel metodo boot del service provider del tuo package:

use Illuminate\Support\Facades\Blade;

/**
 * Avvia i servizi del tuo pacchetto.
 */
public function boot(): void
{
    Blade::component('package-alert', Alert::class);
}

Una volta che il tuo componente è stato registrato, può essere visualizzato usando il suo alias del tag:

<x-package-alert/>

In alternativa, puoi usare il metodo componentNamespace per caricare automaticamente le classi dei componenti per convenzione. Ad esempio, un package Nightshade potrebbe avere i componenti Calendar e ColorPicker che risiedono nello spazio dei nomi Package\Views\Components:

use Illuminate\Support\Facades\Blade;

/**
 * Avvia i servizi del tuo package.
 */
public function boot(): void
{
    Blade::componentNamespace('Nightshade\\Views\\Components', 'nightshade');
}

Questo permetterà di utilizzare i componenti del package tramite il loro spazio dei nomi del fornitore usando la sintassi package-name:::

<x-nightshade::calendar />
<x-nightshade::color-picker />

Blade rileverà automaticamente la classe collegata a questo componente convertendo il nome del componente in PascalCase. Le sottocartelle sono supportate anche usando la notazione "dot".

Rendering dei Componenti

Per visualizzare un componente, puoi usare un tag del componente Blade all’interno di uno dei tuoi template Blade. I tag dei componenti Blade iniziano con la stringa x- seguita dal nome del componente in kebab case:

<x-alert/>

<x-user-profile/>

Se la classe del componente è annidata più profondamente nella directory app/View/Components, puoi usare il carattere . per indicare la profondità ulteriore delle directory. Ad esempio, se assumiamo che un componente si trovi in app/View/Components/Inputs/Button.php, possiamo renderlo in questo modo:

<x-inputs.button/>

Se vuoi visualizzare il tuo componente condizionatamente, puoi definire un metodo shouldRender nella tua classe del componente. Se il metodo shouldRender restituisce false, il componente non verrà visualizzato:

    use Illuminate\Support\Str;

    /**
     * Se il componente deve essere visualizzato
     */
    public function shouldRender(): bool
    {
        return Str::length($this->message) > 0;
    }

Componenti Indice

A volte i componenti fanno parte di un gruppo e potresti voler raggruppare i componenti correlati in una singola directory. Ad esempio, immagina un componente "card" con la seguente struttura delle classi:

App\Views\Components\Card\Card
App\Views\Components\Card\Header
App\Views\Components\Card\Body

Poiché il componente radice Card è annidato all’interno di una directory Card, potresti pensare di dover rendere il componente tramite <x-card.card>. Tuttavia, quando il nome del file di un componente corrisponde al nome della directory del componente, Laravel presume automaticamente che quel componente sia il "componente radice" e ti permette di renderizzare il componente senza ripetere il nome della directory:

<x-card>
    <x-card.header>...</x-card.header>
    <x-card.body>...</x-card.body>
</x-card>

Passare Dati ai Componenti

Puoi passare dati ai componenti Blade usando attributi HTML. I valori primitivi e fissi possono essere passati al componente utilizzando semplici stringhe di attributi HTML. Le espressioni PHP e le variabili devono essere passate al componente tramite attributi che usano il carattere : come prefisso:

<x-alert type="error" :message="$message"/>

Devi definire tutti gli attributi dei dati del componente nel costruttore della sua classe. Tutte le proprietà pubbliche di un componente saranno automaticamente disponibili nella view del componente. Non è necessario passare i dati alla view dal metodo render del componente:

    <?php

    namespace App\View\Components;

    use Illuminate\View\Component;
    use Illuminate\View\View;

    class Alert extends Component
    {
        /**
         * Crea un'istanza del componente.
         */
        public function __construct(
            public string $type,
            public string $message,
        ) {}

        /**
         * Ottiene la view / i contenuti che rappresentano il componente.
         */
        public function render(): View
        {
            return view('components.alert');
        }
    }

Quando il tuo componente viene renderizzato, puoi mostrare il contenuto delle variabili pubbliche del tuo componente stampando le variabili per nome:

<div class="alert alert-{{ $type }}">
    {{ $message }}
</div>

Maiuscole e minuscole

Gli argomenti del costruttore del componente dovrebbero essere specificati usando camelCase, mentre kebab-case dovrebbe essere utilizzato quando si fa riferimento ai nomi degli argomenti nei tuoi attributi HTML. Ad esempio, dato il seguente costruttore del componente:

/**
 * Crea l'istanza del componente.
 */
public function __construct(
    public string $alertType,
) {}

L’argomento $alertType può essere fornito al componente in questo modo:

<x-alert alert-type="danger" />

Sintassi Breve degli Attributi

Quando passi gli attributi ai componenti, puoi utilizzare anche una "sintassi breve per gli attributi". Questo è spesso conveniente poiché i nomi degli attributi corrispondono frequentemente ai nomi delle variabili a cui si riferiscono:

{{-- Short attribute syntax... --}}
<x-profile :$userId :$name />

{{-- Is equivalent to... --}}
<x-profile :user-id="$userId" :name="$name" />

Escape del Rendering degli Attributi

Poiché alcuni framework JavaScript come Alpine.js usano anche attributi con prefisso due punti, puoi usare un prefisso a doppio due punti (::) per informare Blade che l’attributo non è un’espressione PHP. Ad esempio, dato il seguente componente:

<x-button ::class="{ danger: isDeleting }">
    Submit
</x-button>

Il seguente HTML sarà renderizzato da Blade:

<button :class="{ danger: isDeleting }">
    Submit
</button>

Metodi del Componente

Oltre alle variabili pubbliche disponibili nel template del componente, è possibile invocare anche i metodi pubblici del componente. Ad esempio, immagina un componente che ha un metodo isSelected:

/**
 * Determina se l'opzione data è l'opzione attualmente selezionata.
 */
public function isSelected(string $option): bool
{
    return $option === $this->selected;
}

Puoi eseguire questo metodo dal template del tuo componente invocando la variabile corrispondente al nome del metodo:

<option {{ $isSelected($value) ? 'selected' : '' }} value="{{ $value }}">
    {{ $label }}
</option>

Accesso ad Attributi e Slot nelle Classi dei Componenti

I componenti Blade permettono anche di accedere al nome del componente, agli attributi e allo slot all’interno del metodo render della classe. Tuttavia, per accedere a questi dati, devi restituire una closure dal metodo render del tuo componente:

use Closure;

/**
 * Ottieni la vista / contenuti che rappresentano il componente.
 */
public function render(): Closure
{
    return function () {
        return '<div {{ $attributes }}>Contenuto del componente</div>';
    };
}

La closure restituita dal metodo render del tuo componente può ricevere anche un array $data come unico argomento. Questo array conterrà diversi elementi che forniscono informazioni sul componente:

return function (array $data) {
    // $data['componentName'];
    // $data['attributes'];
    // $data['slot'];

    return '<div {{ $attributes }}>Contenuto del componente</div>';
}

Gli elementi nell’array $data non dovrebbero mai essere inseriti direttamente nella stringa Blade restituita dal tuo metodo render, poiché ciò potrebbe permettere l’esecuzione di codice remoto tramite contenuti di attributi malevoli.

Il componentName è uguale al nome usato nel tag HTML dopo il prefisso x-. Quindi, il componentName di <x-alert /> sarà alert. L’elemento attributes conterrà tutti gli attributi presenti sul tag HTML. L’elemento slot è un’istanza di Illuminate\Support\HtmlString con il contenuto dello slot del componente.

La closure deve restituire una stringa. Se la stringa restituita corrisponde a una vista esistente, quella vista verrà renderizzata; altrimenti, la stringa restituita sarà valutata come una vista Blade inline.

Dipendenze Aggiuntive

Se il tuo componente necessita di dipendenze dal service container di Laravel, puoi elencarle prima di qualsiasi attributo dati del componente e saranno iniettate automaticamente dal container:

use App\Services\AlertCreator;

/**
 * Crea l'istanza del componente.
 */
public function __construct(
    public AlertCreator $creator,
    public string $type,
    public string $message,
) {}

Nascondere Attributi / Metodi

Se desideri impedire che alcuni metodi o proprietà pubbliche vengano esposti come variabili nel template del tuo componente, puoi aggiungerli a una proprietà array $except nel tuo componente:

<?php

namespace App\View\Components;

use Illuminate\View\Component;

class Alert extends Component
{
    /**
     * Le proprietà / metodi che non dovrebbero essere esposti al template del componente.
     *
     * @var array
     */
    protected $except = ['type'];

    /**
     * Crea un'istanza del componente.
     */
    public function __construct(
        public string $type,
    ) {}
}

Attributi del Componente

Abbiamo già visto come passare attributi di dati a un componente; tuttavia, a volte potresti aver bisogno di specificare attributi HTML aggiuntivi, come class, che non fanno parte dei dati necessari per il funzionamento di un componente. Di solito, vuoi passare questi attributi aggiuntivi all’elemento radice del template del componente. Ad esempio, immagina di voler rendere un componente alert in questo modo:

<x-alert type="error" :message="$message" class="mt-4"/>

Tutti gli attributi che non fanno parte del costruttore del componente saranno automaticamente aggiunti al "bag di attributi" del componente. Questo bag di attributi è reso automaticamente disponibile al componente tramite la variabile $attributes. Tutti gli attributi possono essere renderizzati all’interno del componente stampando questa variabile:

<div {{ $attributes }}>
    <!-- Component content -->
</div>

L’uso di direttive come @env all’interno dei tag del componente non è supportato al momento. Ad esempio, <x-alert :live="@env('production')"/> non verrà compilato.

Attributi Predefiniti / Combinati

A volte potresti aver bisogno di specificare valori predefiniti per gli attributi o di unire valori aggiuntivi in alcuni degli attributi del componente. Per fare questo, puoi usare il metodo merge del sacchetto degli attributi. Questo metodo è particolarmente utile per definire un insieme di classi CSS predefinite che dovrebbero sempre essere applicate a un componente:

<div {{ $attributes->merge(['class' => 'alert alert-'.$type]) }}>
    {{ $message }}
</div>

Supponiamo che questo componente venga utilizzato in questo modo:

<x-alert type="error" :message="$message" class="mb-4"/>

L’HTML finale del componente renderizzato apparirà come il seguente:

<div class="alert alert-error mb-4">
    <!-- Contenuto della variabile $message -->
</div>

Unire Classi Condizionalmente

A volte potresti voler unire classi se una determinata condizione è true. Puoi farlo tramite il metodo class, che accetta un array di classi dove la chiave dell’array contiene la classe o le classi che desideri aggiungere, mentre il valore è un’espressione booleana. Se l’elemento dell’array ha una chiave numerica, sarà sempre incluso nell’elenco delle classi renderizzate:

<div {{ $attributes->class(['p-4', 'bg-red' => $hasError]) }}>
    {{ $message }}
</div>

Se hai bisogno di unire altri attributi al tuo componente, puoi concatenare il metodo merge al metodo class:

<button {{ $attributes->class(['p-4'])->merge(['type' => 'button']) }}>
    {{ $slot }}
</button>

Se hai bisogno di aggiungere classi condizionalmente ad altri elementi HTML che non dovrebbero ricevere attributi uniti, puoi usare la @class directive.

Unione di Attributi diversi da class

Quando si uniscono attributi che non sono class, i valori forniti al metodo merge saranno considerati i valori "predefiniti" dell’attributo. Tuttavia, a differenza dell’attributo class, questi attributi non verranno uniti con i valori degli attributi iniettati. Invece, saranno sovrascritti. Ad esempio, l’implementazione di un componente button potrebbe essere la seguente:

<button {{ $attributes->merge(['type' => 'button']) }}>
    {{ $slot }}
</button>

Per rendere il componente button con un type personalizzato, può essere specificato durante l’utilizzo del componente. Se non viene specificato un type, verrà usato button:

<x-button type="submit">
    Submit
</x-button>

L’HTML renderizzato del componente button in questo esempio sarà:

<button type="submit">
    Submit
</button>

Se desideri che un attributo diverso da class abbia il suo valore predefinito e i valori iniettati vengano uniti, puoi usare il metodo prepends. In questo esempio, l’attributo data-controller inizierà sempre con profile-controller e eventuali ulteriori valori data-controller iniettati verranno aggiunti dopo questo valore predefinito:

<div {{ $attributes->merge(['data-controller' => $attributes->prepends('profile-controller')]) }}>
    {{ $slot }}
</div>

Recupero e Filtraggio degli Attributi

Puoi filtrare gli attributi usando il metodo filter. Questo metodo accetta una closure che deve restituire true se desideri mantenere l’attributo nella raccolta degli attributi:

{{ $attributes->filter(fn (string $value, string $key) => $key == 'foo') }}

Per comodità, puoi usare il metodo whereStartsWith per recuperare tutti gli attributi le cui chiavi iniziano con una determinata stringa:

{{ $attributes->whereStartsWith('wire:model') }}

Al contrario, il metodo whereDoesntStartWith può essere usato per escludere tutti gli attributi le cui chiavi iniziano con una determinata stringa:

{{ $attributes->whereDoesntStartWith('wire:model') }}

Usando il metodo first, puoi visualizzare il primo attributo in una raccolta di attributi:

{{ $attributes->whereStartsWith('wire:model')->first() }}

Se vuoi verificare se un attributo è presente sul componente, puoi usare il metodo has. Questo metodo accetta il nome dell’attributo come unico argomento e restituisce un booleano che indica se l’attributo è presente o meno:

@if ($attributes->has('class'))
    <div>Class attribute is present</div>
@endif

Se viene passato un array al metodo has, il metodo determinerà se tutti gli attributi forniti sono presenti sul componente:

@if ($attributes->has(['name', 'class']))
    <div>All of the attributes are present</div>
@endif

Il metodo hasAny può essere usato per determinare se uno qualsiasi degli attributi forniti è presente sul componente:

@if ($attributes->hasAny(['href', ':href', 'v-bind:href']))
    <div>One of the attributes is present</div>
@endif

Puoi recuperare il valore di un attributo specifico usando il metodo get:

{{ $attributes->get('class') }}

Parole chiave riservate

Per impostazione predefinita, alcune parole chiave sono riservate per l’uso interno di Blade per renderizzare i componenti. Le seguenti parole chiave non possono essere definite come proprietà pubbliche o nomi di metodi all’interno dei tuoi componenti:

  • data
  • render
  • resolveView
  • shouldRender
  • view
  • withAttributes
  • withName

Slots

Spesso avrai bisogno di passare contenuto aggiuntivo al tuo componente tramite "slots". Gli slot dei componenti vengono visualizzati utilizzando la variabile $slot. Per capire meglio questo concetto, immaginiamo che un componente alert abbia il seguente markup:

<!-- /resources/views/components/alert.blade.php -->

<div class="alert alert-danger">
    {{ $slot }}
</div>

Possiamo passare contenuto allo slot inserendo contenuto nel componente:

<x-alert>
    <strong>Whoops!</strong> Qualcosa è andato storto!
</x-alert>

A volte un componente potrebbe aver bisogno di mostrare più slot diversi in posizioni differenti all’interno del componente. Modifichiamo il nostro componente alert per permettere l’uso di uno slot "title":

<!-- /resources/views/components/alert.blade.php -->

<span class="alert-title">{{ $title }}</span>

<div class="alert alert-danger">
    {{ $slot }}
</div>

Puoi definire il contenuto dello slot nominato usando il tag x-slot. Qualsiasi contenuto che non è all’interno di un tag x-slot esplicito verrà passato al componente nella variabile $slot:

<x-alert>
    <x-slot:title>
        Errore del Server
    </x-slot>

    <strong>Whoops!</strong> Qualcosa è andato storto!
</x-alert>

Puoi usare il metodo isEmpty di uno slot per verificare se lo slot contiene contenuto:

<span class="alert-title">{{ $title }}</span>

<div class="alert alert-danger">
    @if ($slot->isEmpty())
        Questo è il contenuto predefinito se lo slot è vuoto.
    @else
        {{ $slot }}
    @endif
</div>

Inoltre, il metodo hasActualContent può essere utilizzato per verificare se lo slot contiene contenuto "reale" che non è un commento HTML:

@if ($slot->hasActualContent())
    Lo scope contiene contenuto non-commento.
@endif

Scoped Slot

Se hai utilizzato un framework JavaScript come Vue, potresti conoscere gli "scoped slot", che permettono di accedere a dati o metodi del componente all’interno del tuo slot. In Laravel puoi ottenere un comportamento simile definendo metodi o proprietà pubbliche nel tuo componente e accedendo al componente dentro lo slot tramite la variabile $component. In questo esempio, supponiamo che il componente x-alert abbia definito un metodo pubblico formatAlert nella sua classe:

<x-alert>
    <x-slot:title>
        {{ $component->formatAlert('Server Error') }}
    </x-slot>

    <strong>Whoops!</strong> Something went wrong!
</x-alert>

Attributi degli Slot

Come i componenti Blade, puoi assegnare attributi aggiuntivi agli slot, come i nomi delle classi CSS:

<x-card class="shadow-sm">
    <x-slot:heading class="font-bold">
        Intestazione
    </x-slot>

    Contenuto

    <x-slot:footer class="text-sm">
        Piè di pagina
    </x-slot>
</x-card>

Per interagire con gli attributi degli slot, puoi accedere alla proprietà attributes della variabile dello slot. Per maggiori informazioni su come interagire con gli attributi, consulta la documentazione su component attributes:

@props([
    'heading',
    'footer',
])

<div {{ $attributes->class(['border']) }}>
    <h1 {{ $heading->attributes->class(['text-lg']) }}>
        {{ $heading }}
    </h1>

    {{ $slot }}

    <footer {{ $footer->attributes->class(['text-gray-700']) }}>
        {{ $footer }}
    </footer>
</div>

Viste Inline dei Componenti

Per componenti molto piccoli, potrebbe risultare complicato gestire sia la classe del componente sia il template della vista. Per questo motivo, puoi restituire direttamente il markup del componente dal metodo render:

/**
 * Ottieni la vista / i contenuti che rappresentano il componente.
 */
public function render(): string
{
    return <<<'blade'
        <div class="alert alert-danger">
            {{ $slot }}
        </div>
    blade;
}

Generare Componenti di Vista Inline

Per creare un componente che rende una vista inline, puoi usare l’opzione inline quando esegui il comando make:component:

php artisan make:component Alert --inline

Componenti Dinamici

A volte potresti aver bisogno di renderizzare un componente senza sapere quale componente verrà utilizzato fino al momento dell’esecuzione. In questa situazione, puoi usare il componente dynamic-component di Laravel per renderizzare il componente basato su un valore o una variabile durante l’esecuzione:

// $componentName = "secondary-button";

<x-dynamic-component :component="$componentName" class="mt-4" />

Registrazione manuale dei componenti

La seguente documentazione sulla registrazione manuale dei componenti è principalmente rivolta a chi scrive package Laravel che includono componenti di vista. Se non stai scrivendo un package, questa sezione della documentazione sui componenti potrebbe non essere rilevante per te.

Quando crei componenti per la tua applicazione, questi vengono scoperti automaticamente nelle directory app/View/Components e resources/views/components.

Tuttavia, se stai creando un package che utilizza componenti Blade o posizionando i componenti in directory non convenzionali, dovrai registrare manualmente la classe del componente e il suo alias di tag HTML affinché Laravel sappia dove trovarlo. Di solito, dovresti registrare i tuoi componenti nel metodo boot del service provider del tuo package:

use Illuminate\Support\Facades\Blade;
use VendorPackage\View\Components\AlertComponent;

/**
 * Bootstrap dei servizi del tuo package.
 */
public function boot(): void
{
    Blade::component('package-alert', AlertComponent::class);
}

Una volta registrato il tuo componente, puoi utilizzarlo con il suo alias di tag:

<x-package-alert/>

Autoloading dei componenti del package

In alternativa, puoi usare il metodo componentNamespace per caricare automaticamente le classi dei componenti per convenzione. Per esempio, un pacchetto Nightshade potrebbe avere i componenti Calendar e ColorPicker che risiedono nel namespace Package\Views\Components:

    use Illuminate\Support\Facades\Blade;

    /**
     * Bootstrap your package's services.
     */
    public function boot(): void
    {
        Blade::componentNamespace('Nightshade\\Views\\Components', 'nightshade');
    }

Questo permetterà di usare i componenti del package tramite il namespace del vendor usando la sintassi nome-package:::

<x-nightshade::calendar />
<x-nightshade::color-picker />

Blade rileverà automaticamente la classe collegata a questo componente convertendo il nome del componente in PascalCase. Le sottocartelle sono supportate anche tramite la notazione a punti.

Componenti Anonimi

Simili ai componenti inline, i componenti anonimi offrono un modo per gestire un componente tramite un unico file. Tuttavia, i componenti anonimi utilizzano un solo file di vista e non hanno una classe associata. Per definire un componente anonimo, devi solo inserire un template Blade nella directory resources/views/components. Ad esempio, supponendo di aver definito un componente in resources/views/components/alert.blade.php, puoi renderizzarlo semplicemente così:

<x-alert/>

Puoi usare il carattere . per indicare se un componente è annidato più in profondità nella directory components. Ad esempio, supponendo che il componente sia definito in resources/views/components/inputs/button.blade.php, puoi renderizzarlo così:

<x-inputs.button/>

Componenti Indice Anonimi

Talvolta, quando un componente è composto da molti template Blade, potresti voler raggruppare i template del componente in una singola cartella. Ad esempio, immagina un componente "accordion" con la seguente struttura di directory:

/resources/views/components/accordion.blade.php
/resources/views/components/accordion/item.blade.php

Questa struttura di directory ti permette di renderizzare il componente accordion e i suoi elementi in questo modo:

<x-accordion>
    <x-accordion.item>
        ...
    </x-accordion.item>
</x-accordion>

Tuttavia, per poter renderizzare il componente accordion tramite x-accordion, siamo stati costretti a posizionare il template del componente "index" nella directory resources/views/components invece di annidarlo all’interno della directory accordion insieme agli altri template correlati.

Fortunatamente, Blade permette di posizionare un file che corrisponde al nome della directory del componente all’interno della stessa directory. Quando questo template esiste, può essere renderizzato come elemento "root" del componente anche se è annidato all’interno di una directory. Quindi, possiamo continuare a usare la stessa sintassi Blade mostrata nell’esempio sopra; tuttavia, modificheremo la nostra struttura di directory in questo modo:

/resources/views/components/accordion/accordion.blade.php
/resources/views/components/accordion/item.blade.php

Proprietà dei Dati / Attributi

Poiché i componenti anonimi non possiedono una classe associata, potresti chiederti come distinguere quali dati passare al componente come variabili e quali attributi inserire nell’attribute bag del componente.

Puoi specificare quali attributi devono essere considerati variabili di dati utilizzando la direttiva @props all’inizio del template Blade del tuo componente. Tutti gli altri attributi del componente saranno disponibili nell’attribute bag del componente. Se desideri assegnare un valore predefinito a una variabile di dati, puoi specificare il nome della variabile come chiave dell’array e il valore predefinito come valore dell’array:

<!-- /resources/views/components/alert.blade.php -->

@props(['type' => 'info', 'message'])

<div {{ $attributes->merge(['class' => 'alert alert-'.$type]) }}>
    {{ $message }}
</div>

Data la definizione del componente sopra, possiamo renderizzarlo in questo modo:

<x-alert type="error" :message="$message" class="mb-4"/>

Accesso ai Dati del Genitore

A volte potresti voler accedere ai dati di un componente genitore all’interno di un componente figlio. In questi casi, puoi usare la direttiva @aware. Ad esempio, immagina di costruire un componente menu complesso composto da un genitore <x-menu> e figli <x-menu.item>:

<x-menu color="purple">
    <x-menu.item>...</x-menu.item>
    <x-menu.item>...</x-menu.item>
</x-menu>

Il componente <x-menu> potrebbe avere un’implementazione come la seguente:

<!-- /resources/views/components/menu/index.blade.php -->

@props(['color' => 'gray'])

<ul {{ $attributes->merge(['class' => 'bg-'.$color.'-200']) }}>
    {{ $slot }}
</ul>

Poiché la proprietà color è stata passata solo al genitore (<x-menu>), non sarà disponibile all’interno di <x-menu.item>. Tuttavia, se usiamo la direttiva @aware, possiamo renderla disponibile anche in <x-menu.item>:

<!-- /resources/views/components/menu/item.blade.php -->

@aware(['color' => 'gray'])

<li {{ $attributes->merge(['class' => 'text-'.$color.'-800']) }}>
    {{ $slot }}
</li>

La direttiva @aware non può accedere ai dati del genitore che non vengono passati esplicitamente al componente genitore tramite attributi HTML. I valori predefiniti di @props che non vengono passati esplicitamente al componente genitore non possono essere accessibili dalla direttiva @aware.

Percorsi dei Componenti Anonimi

Come discusso in precedenza, i componenti anonimi vengono solitamente definiti posizionando un template Blade nella directory resources/views/components. Tuttavia, potresti voler registrare altri percorsi di componenti anonimi con Laravel oltre al percorso predefinito.

Il metodo anonymousComponentPath accetta come primo argomento il "path" alla posizione del componente anonimo e come secondo argomento opzionale un "namespace" sotto cui i componenti dovrebbero essere collocati. Tipicamente, questo metodo dovrebbe essere chiamato dal metodo boot di uno dei provider di servizi della tua applicazione:

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        Blade::anonymousComponentPath(__DIR__.'/../components');
    }

Quando i percorsi dei componenti sono registrati senza un prefisso specificato come nell’esempio sopra, possono essere resi nei tuoi componenti Blade senza un prefisso corrispondente. Ad esempio, se esiste un componente panel.blade.php nel percorso registrato sopra, può essere reso così:

<x-panel />

I "namespace" di prefisso possono essere forniti come secondo argomento al metodo anonymousComponentPath:

    Blade::anonymousComponentPath(__DIR__.'/../components', 'dashboard');

Quando viene fornito un prefisso, i componenti all’interno di quel "namespace" possono essere resi prefissando il namespace al nome del componente quando viene renderizzato:

<x-dashboard::panel />

Creazione di Layout

Layouts Utilizzando i Componenti

La maggior parte delle applicazioni web mantiene lo stesso layout generale su diverse pagine. Sarebbe estremamente laborioso e difficile mantenere la nostra applicazione se dovessimo ripetere l’intero HTML del layout in ogni vista che creiamo. Fortunatamente, è comodo definire questo layout come un unico Blade component e poi utilizzarlo in tutta l’applicazione.

Definizione del Componente Layout

Per esempio, immaginiamo di creare un’applicazione per una lista "todo". Potremmo definire un componente layout che appare come segue:

<!-- resources/views/components/layout.blade.php -->

<html>
    <head>
        <title>{{ $title ?? 'Todo Manager' }}</title>
    </head>
    <body>
        <h1>Todos</h1>
        <hr/>
        {{ $slot }}
    </body>
</html>

Applicare il Componente Layout

Una volta definito il componente layout, possiamo creare una vista Blade che utilizza il componente. In questo esempio, definiamo una vista semplice che mostra la nostra lista di attività:

<!-- resources/views/tasks.blade.php -->

<x-layout>
    @foreach ($tasks as $task)
        <div>{{ $task }}</div>
    @endforeach
</x-layout>

Ricorda, il contenuto iniettato in un componente verrà fornito alla variabile predefinita $slot all’interno del nostro componente layout. Come forse hai notato, il nostro layout rispetta anche uno slot $title se fornito; altrimenti, viene mostrato un titolo predefinito. Possiamo inserire un titolo personalizzato dalla nostra vista della lista di attività utilizzando la sintassi dello slot standard discussa nella documentazione dei componenti:

<!-- resources/views/tasks.blade.php -->

<x-layout>
    <x-slot:title>
        Titolo Personalizzato
    </x-slot>

    @foreach ($tasks as $task)
        <div>{{ $task }}</div>
    @endforeach
</x-layout>

Ora che abbiamo definito le nostre viste layout e task, dobbiamo solo restituire la vista task da una rotta:

use App\Models\Task;

Route::get('/tasks', function () {
    return view('tasks', ['tasks' => Task::all()]);
});

Layouts Utilizzando l’Eredità dei Template

Definire un Layout

I layout possono essere creati anche tramite "ereditarietà di template". Questo era il principale metodo per costruire applicazioni prima dell’introduzione dei componenti.

Per iniziare, diamo un’occhiata a un esempio semplice. Prima esamineremo un layout di pagina. Poiché la maggior parte delle applicazioni web mantiene lo stesso layout generale su diverse pagine, è conveniente definire questo layout come una singola vista Blade:

<!-- resources/views/layouts/app.blade.php -->

<html>
    <head>
        <title>Nome App - @yield('title')</title>
    </head>
    <body>
        @section('sidebar')
            Questa è la sidebar principale.
        @show

        <div class="container">
            @yield('content')
        </div>
    </body>
</html>

Come puoi vedere, questo file contiene il markup HTML tipico. Tuttavia, nota le direttive @section e @yield. La direttiva @section definisce una sezione di contenuto, mentre la direttiva @yield viene utilizzata per visualizzare il contenuto di una determinata sezione.

Ora che abbiamo definito un layout per la nostra applicazione, definiamo una pagina figlia che eredita il layout.

Estendere un Layout

Quando definisci una vista figlia, usa la direttiva Blade @extends per specificare quale layout la vista figlia dovrebbe "ereditare". Le viste che estendono un layout Blade possono inserire contenuto nelle sezioni del layout usando le direttive @section. Ricorda, come visto nell’esempio sopra, il contenuto di queste sezioni verrà visualizzato nel layout usando @yield:

<!-- resources/views/child.blade.php -->

@extends('layouts.app')

@section('title', 'Page Title')

@section('sidebar')
    @@parent

    <p>Questo viene aggiunto alla sidebar principale.</p>
@endsection

@section('content')
    <p>Questo è il mio contenuto principale.</p>
@endsection

In questo esempio, la sezione sidebar utilizza la direttiva @@parent per aggiungere (anziché sovrascrivere) contenuto alla sidebar del layout. La direttiva @@parent verrà sostituita dal contenuto del layout quando la vista viene renderizzata.

Contrariamente all’esempio precedente, questa sezione sidebar termina con @endsection invece di @show. La direttiva @endsection definisce solo una sezione mentre @show definisce e mostra immediatamente la sezione.

La direttiva @yield accetta anche un valore predefinito come secondo parametro. Questo valore verrà visualizzato se la sezione che viene usata non è stata definita:

@yield('content', 'Contenuto predefinito')

Moduli

Campo CSRF

Ogni volta che definisci un modulo HTML nella tua applicazione, dovresti includere un campo token CSRF nascosto nel modulo affinché il middleware la protezione CSRF possa validare la richiesta. Puoi usare la direttiva Blade @csrf per generare il campo token:

<form method="POST" action="/profile">
    @csrf

    ...
</form>

Campo Metodo

Poiché i form HTML non possono inviare richieste PUT, PATCH o DELETE, devi aggiungere un campo nascosto _method per simulare questi verbi HTTP. La direttiva Blade @method può creare questo campo per te:

<form action="/foo/bar" method="POST">
    @method('PUT')

    ...
</form>

Errori di Validazione

La direttiva @error può essere utilizzata per verificare rapidamente se esistono messaggi di errore di validazione per un dato attributo. All’interno di una direttiva @error, puoi stampare la variabile $message per mostrare il messaggio di errore:

<!-- /resources/views/post/create.blade.php -->

<label for="title">Titolo del Post</label>

<input
    id="title"
    type="text"
    class="@error('title') is-invalid @enderror"
/>

@error('title')
    <div class="alert alert-danger">{{ $message }}</div>
@enderror

Poiché la direttiva @error viene compilata come un’istruzione "if", puoi usare la direttiva @else per mostrare contenuto quando non c’è un errore per un attributo:

<!-- /resources/views/auth.blade.php -->

<label for="email">Indirizzo Email</label>

<input
    id="email"
    type="email"
    class="@error('email') is-invalid @else is-valid @enderror"
/>

Puoi passare il nome di un specifico error bag come secondo parametro alla direttiva @error per recuperare i messaggi di errore di validazione nelle pagine che contengono più form:

<!-- /resources/views/auth.blade.php -->

<label for="email">Indirizzo Email</label>

<input
    id="email"
    type="email"
    class="@error('email', 'login') is-invalid @enderror"
/>

@error('email', 'login')
    <div class="alert alert-danger">{{ $message }}</div>
@enderror

Stacks

Blade ti permette di aggiungere dei contenuti a stack nominati che possono essere visualizzati in un’altra vista o layout. Questo può essere particolarmente utile per specificare eventuali librerie JavaScript necessarie alle tue viste figlie:

@push('scripts')
    <script src="/example.js"></script>
@endpush

Se desideri @push contenuto solo se una determinata espressione booleana è true, puoi utilizzare la direttiva @pushIf:

@pushIf($shouldPush, 'scripts')
    <script src="/example.js"></script>
@endPushIf

Puoi aggiungere a uno stack tutte le volte che vuoi. Per rendere il contenuto completo dello stack, passa il nome dello stack alla direttiva @stack:

<head>
    <!-- Contenuti dell'Head -->

    @stack('scripts')
</head>

Se desideri anteporre contenuto all’inizio di uno stack, dovresti usare la direttiva @prepend:

@push('scripts')
    Questo sarà il secondo...
@endpush

// Successivamente...

@prepend('scripts')
    Questo sarà il primo...
@endprepend

Service Injection

La direttiva @inject può essere utilizzata per ottenere un servizio dal service container di Laravel. Il primo argomento passato a @inject è il nome della variabile in cui verrà inserito il servizio, mentre il secondo argomento è il nome della classe o dell’interfaccia del servizio che si desidera risolvere:

@inject('metrics', 'App\Services\MetricsService')

<div>
    Monthly Revenue: {{ $metrics->monthlyRevenue() }}.
</div>

Rendering di Template Blade Inline

A volte potresti aver bisogno di trasformare una stringa di template Blade grezza in HTML valido. Puoi farlo utilizzando il metodo render fornito dalla facciata Blade. Il metodo render accetta la stringa del template Blade e un array opzionale di dati da fornire al template:

use Illuminate\Support\Facades\Blade;

return Blade::render('Hello, {{ $name }}', ['name' => 'Julian Bashir']);

Laravel renderizza i template Blade inline scrivendoli nella directory storage/framework/views. Se vuoi che Laravel rimuova questi file temporanei dopo aver renderizzato il template Blade, puoi fornire l’argomento deleteCachedView al metodo:

return Blade::render(
    'Hello, {{ $name }}',
    ['name' => 'Julian Bashir'],
    deleteCachedView: true
);

Rendering di Frammenti Blade

Quando si utilizzano framework frontend come Turbo e htmx, potresti dover restituire solo una parte di un template Blade nella tua risposta HTTP. I "frammenti" di Blade ti permettono di fare proprio questo. Per iniziare, inserisci una sezione del tuo template Blade tra le direttive @fragment e @endfragment:

@fragment('user-list')
    <ul>
        @foreach ($users as $user)
            <li>{{ $user->name }}</li>
        @endforeach
    </ul>
@endfragment

Poi, durante il rendering della vista che utilizza questo template, puoi usare il metodo fragment per specificare che solo il frammento indicato debba essere incluso nella risposta HTTP:

return view('dashboard', ['users' => $users])->fragment('user-list');

Il metodo fragmentIf permette di restituire condizionalmente un frammento di una vista in base a una determinata condizione. Altrimenti, verrà restituita l’intera vista:

return view('dashboard', ['users' => $users])
    ->fragmentIf($request->hasHeader('HX-Request'), 'user-list');

I metodi fragments e fragmentsIf consentono di restituire più frammenti di vista nella risposta. I frammenti verranno concatenati insieme:

view('dashboard', ['users' => $users])
    ->fragments(['user-list', 'comment-list']);

view('dashboard', ['users' => $users])
    ->fragmentsIf(
        $request->hasHeader('HX-Request'),
        ['user-list', 'comment-list']
    );

Estendere Blade

Blade permette di definire direttive personalizzate utilizzando il metodo directive. Quando il compilatore Blade incontra una direttiva personalizzata, chiama il callback fornito con l’espressione contenuta nella direttiva.

Il seguente esempio crea una direttiva @datetime($var) che formatta una variabile $var, che dovrebbe essere un’istanza di DateTime:

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Registra i servizi dell'applicazione.
     */
    public function register(): void
    {
        // ...
    }

    /**
     * Avvia i servizi dell'applicazione.
     */
    public function boot(): void
    {
        Blade::directive('datetime', function (string $expression) {
            return "<?php echo ($expression)->format('m/d/Y H:i'); ?>";
        });
    }
}

Come puoi vedere, concatenaremo il metodo format sull’espressione passata alla direttiva. Quindi, in questo esempio, il PHP finale generato da questa direttiva sarà:

<?php echo ($var)->format('m/d/Y H:i'); ?>

Dopo aver aggiornato la logica di una direttiva Blade, sarà necessario eliminare tutte le viste Blade cache. Le viste Blade cache possono essere rimosse usando il comando Artisan view:clear.

Gestori di echo personalizzati

Se tenti di "echo" un oggetto usando Blade, verrà invocato il metodo __toString dell’oggetto. Il metodo __toString è uno dei "metodi magici" integrati di PHP. Tuttavia, a volte potresti non avere il controllo sul metodo __toString di una determinata classe, come quando la classe con cui stai interagendo appartiene a una libreria di terze parti.

In questi casi, Blade ti permette di registrare un gestore di echo personalizzato per quel particolare tipo di oggetto. Per fare ciò, dovresti invocare il metodo stringable di Blade. Il metodo stringable accetta una closure. Questa closure dovrebbe specificare il tipo di oggetto di cui è responsabile la renderizzazione. Di solito, il metodo stringable dovrebbe essere invocato all’interno del metodo boot della classe AppServiceProvider della tua applicazione:

use Illuminate\Support\Facades\Blade;
use Money\Money;

/**
 * Bootstrap any application services.
 */
public function boot(): void
{
    Blade::stringable(function (Money $money) {
        return $money->formatTo('en_GB');
    });
}

Una volta definito il tuo gestore di echo personalizzato, puoi semplicemente echo l’oggetto nel tuo template Blade:

Costo: {{ $money }}

Condizioni If personalizzate

Creare una direttiva personalizzata a volte risulta più complesso del necessario quando si definiscono semplici condizioni personalizzate. Per questo motivo, Blade fornisce il metodo Blade::if che permette di definire rapidamente direttive condizionali personalizzate usando le closures. Ad esempio, definiamo una condizione personalizzata che verifica il "disk" predefinito configurato per l’applicazione. Possiamo farlo nel metodo boot del nostro AppServiceProvider:

use Illuminate\Support\Facades\Blade;

/**
 * Avvia i servizi dell'applicazione.
 */
public function boot(): void
{
    Blade::if('disk', function (string $value) {
        return config('filesystems.default') === $value;
    });
}

Una volta definita la condizione personalizzata, puoi usarla all’interno dei tuoi template:

@disk('local')
    <!-- L'applicazione utilizza il disco locale... -->
@elsedisk('s3')
    <!-- L'applicazione utilizza il disco s3... -->
@else
    <!-- L'applicazione utilizza un altro disco... -->
@enddisk

@unlessdisk('local')
    <!-- L'applicazione non utilizza il disco locale... -->
@enddisk
Lascia un commento

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *