Direttive

Extends

Questa direttiva serve all’interno di una view per includere un layout; la direttiva riportata sotto indica alla view di includere il file resources\views\templates\layout.blade.php e riporta solo il percorso finale; il folder templates e il nome del file layout.blade.php sono stati creati ad hoc…non c’è una struttura folder fissa da seguire. Inoltre è possibile avere più layout all’interno dello stesso progetto quindi conviene dare dei nomi parlanti.

@extends('templates.layout')

NB: nel corso su Udemy il layout è copiato da un template standard di Bootstrap.

Yield

All’interno del layout questa direttiva serve per aggiungere del contenuto; il secondo parametro è il default nel caso il valore sia vuoto; esempio:

# scrive il valore di title passato dalla view; se manca viene scritto Home
<title>@yield('title', 'Home')</title>

# scrive il valore di content passato dalla view
<main role="main" class="container">
@yield('content')
</main>

Section

All’interno della view serve per definire una sezione che poi sarà richiamata nel layout tramite yield; può essere una singola riga oppure più righe; nel caso ci siano più righe la direttiva va chiusa con @endsection oppure @stop.

# riga singola con valore
@section('title', $title)

# la direttiva è aperta e chiusa, con del codice al suo interno
@section('content')
<h1>{{$title}} Template Blade</h1>

@if ($staff)
    <ul>
    @foreach($staff as $person)
        <li>{{$person['name']}} {{$person['lastname']}}</li>
    @endforeach
    </ul>
@endif
@endsection

All’interno di un layout definisce una sezione che termina con @show; questa direttiva serve per mostrare subito il contenuto della sezione. Facendo delle prove ho capito che senza @show il contenuto della view è irrilevante e non sarà incluso (piuttosto usare @yield).

@section('footer')
...
...
...
@show

Se nella view definiamo una sezione con lo stesso nome essa andrà a sovrascrivere la sezione nel layout SOLO nel caso il layout contenga @show al fondo della sezione.

@section('footer')
...
...
...
@stop

Per mantere il contenuto della sezione nel layout dobbiamo usare la direttiva @parent; così facendo prima di includere il contenuto della view sarà aggiunto il contenuto del layout.

@section('footer')
    @parent
    ...
@stop

Component

Sono simili alle section; i file si creano dentro il percorso resources\views\components\nome_componente.blade.php, mentre il codice html è nella view, a cui bisogna aggiungere dei segnaposto generici.

<div class="card" style="width: 18rem;">
  <img class="card-img-top" src="{{$img_path}}" alt="{{$img_title}}" title="{{$img_title}}">
  <div class="card-body">
    <h5 class="card-title">{{$img_title}}</h5>
    {{$slot}}
  </div>
</div>

Per passare i valori ai components si possono usare 2 modi

Array

Variabili e valori vengono passati come array nel secondo parametro del componente, mentre {{$slot}} viene popolato come codice html generico fuori dall’array ma all’interno del componente.

NB: ho provato ad aggiungere una variabile slot all’array ma non viene considerata.

@section('content')
    <h1>Blog</h1>
    @component('components.card',
    [
        'img_path' => 'https://lamberto.altervista.org/wp-content/uploads/2020/05/paperinik-pkna-il-vento-del-tempo-320x476.jpg',
        'img_title' => 'My Image Blog',
    ]
    )
    <p>PK e il Razziatore</p>
    @endcomponent
@endsection

Usando @slot

In questo caso la coppia variabile-valore è dentro la direttiva @slot, mentre il contenuto generico che sostituisce {{$slot}} nella view resta compreso all’interno del componente senza riferimenti.

@section('content')
    <h1>Blog</h1>
    @component('components.card')
        @slot('img_path', 'https://lamberto.altervista.org/wp-content/uploads/2020/05/Lupo-alberto-320x470.jpg')
        @slot('img_title', 'Lupo Alberto')
        <p>Ehilà Beppe!!!</p>
    @endcomponent
@endsection

Componente basato su classe

La documentazione si trova qui; rivedere corso sezione 7 lezioni 48-49-50.

Il comando per creare un componente è php artisan make:component nome_componente; lega un componente ad una view ed allo stesso tempo ad un template ed un controller.

Il comando php artisan make:component Alert crea la struttura folder/file app\View\Components\Alert.php e resources\views\components\alert.blade.php.


Aggiungendo il parametro --inline al comando sopra Laravel non crea la view corrispondente e nella funzione render() dentro la classe scrive direttamente il codice html, delimitato da <<<<<'blade' e blade.

public function render()
{
    return <<<'blade'
        <div class="alert alert-danger">
            {{ $slot }}
        </div>
    blade;
}

In app\View\Components\Alert.php bisogna dichiarare le variabili $info e $message come pubbliche all’inizio della classe, passarle alla funzione __construct() (eventualmente settare dei valori default) e richiamarle al suo interno. La funzione render() si occuperà di mostrare il componente.

namespace App\View\Components;

use Illuminate\View\Component;

class Alert extends Component
{
    public $info;
    public $message;
    
    /**
     * Create a new component instance.
     *
     * @return void
     */
    public function __construct($info = 'danger', $message = 'Ciao')
    {
        $this->info = $info;
        $this->message = $message;
    }

    /**
     * Get the view / contents that represent the component.
     *
     * @return \Illuminate\View\View|string
     */
    public function render()
    {
        return view('components.alert');
    }
}

Di seguito la view resources\views\components\alert.blade.php modificata per valorizzare le 2 variabili create.

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

In una view il componente si richiama con la dicitura <x-alert/>, dove alert è il nome del componente scelto al momento della creazione. Per passare un valore si usano i 2 punti davanti al nome della variabile usata nella classe; notare che, nell’esempio sotto, passando i valori tra apici singoli sono considerati delle stringhe; senza apici singoli Laravel le considera variabili PHP.

<x-alert :info="'info'" :message="'testo'"/>

Nell’esempio sotto il valore di :name non è più una stringa ma una variabile $name proveniente dalla route routes\web.php, recuparata dalla GET dell’url. Ovviamente bisogna modificare:

  • la view del componente per mostare la nuova variabile
  • la classe Alert come sopra
<x-alert :name="$name" :info="'info'" :message="'testo'"/>

Route::view('/', 'welcome', ['name' => Request::input('name')]);

Slot

Si mette dentro i componenti ed indica “qualunque altra cosa che non è passata attraverso le variabili”; generalmente è del codice html e nella view valorizza {{$slot}}.

Include

Serve per aggiungere del codice alla pagina; è simile ad un componente ma variabili e valori devono esistere globalmente e provengono dal controller invece che dalla view, nella quale c’è solo il richiamo.

Una sostanziale differenza è che nel controller DEVO specificare slot come se fosse una variabile normale, mentre nella view è opzionale.

NB: l’esempio sotto usa l’include come un componente ma non mi pare un’idea pratica.

# dentro la view resources\views\blog.blade.php
@include('components.card')

# dentro il controller app\Http\Controllers\PageController.php
public function blog()
{
    return view('blog',
        [
            'img_path' => 'https://lamberto.altervista.org/wp-content/uploads/2020/05/STURM_Basket_01_low_2-320x320.jpg',
            'img_title' => 'Sturmtruppen',
            'slot' => 'Sturmtruppen play basketball'
        ]
    );
}

Se non si vuole usare il controller i valori si possono passare come array, nel secondo parametro della direttiva, esattamente come il componente. Non riporterò questo esempio proprio perchè è identico al componente.