Blade è un potente e semplice motore di template fornito da laravel che rende la costruzione delle view molto duttile e semplice.
All’interno delle blade view, l’utente è libero di utilizzare puro codice php oltre alle direttive fornite dal blade engine , questo perché Laravel compila tutto in codice php e lo salva in un’apposita cache fino a quando non subisce modifiche. Tutto ciò rende le view create, utilizzando il blade engine, particolarmente efficienti. Le view vengono salvate a partire dalla cartella resources/views e terminano con l’estensione .blade.php.
Vediamo ora le principali caratteristiche di questo sistema:
La principale peculiarità del blade engine è quella di consentire l’ereditarietà tra le views, mi spiego meglio… poiché molte applicazioni web mantengono un layout comune, sarebbe molto comodo avere una pagina master, che definisce il layout comune, dalla quale poi le singole pagine ereditano e alla quale inviano contenuti in apposite sezioni predisposte.
Utilizziamo un esempio per chiarire meglio:
<!—pagina salvata come resources/views/layouts/app.blade.php –>
<html> <head> <title>App Name - @yield('title')</title> </head> <body> @section('sidebar') This is the master sidebar. @show <div class="container"> @yield('content') </div> </body> </html>
In questa pagina, oltre al comune mark-up html, sono presenti alcune direttive, @section e @yield;
la direttiva @section definisce una porzione di contenuti, mentre la direttiva @yield serve a richiamare e visualizzare i contenuti di una specifica @section.
A questo punto, dopo aver definito il layout, definiamo una pagina child che lo utilizza:
<!—pagina salvata in resources/views/child.blade.php –>
@extends('layouts.app') @section('title', 'Titolo pagina') @section('sidebar') @parent <p>Contenuto aggiunto alla sidebar.</p> @endsection @section('content') <p>Corpo del documento.</p> @endsection
Possiamo subito notare che la prima direttiva @extends(‘layouts.app’) , dichiara che questa pagina eredita il suo layout dalla pagina memorizzata in resources/view/layouts e con nome file app.blade.php (non è necessario specificare il suffisso .blade.php).
La seconda direttiva @section(‘title’, ‘Titolo pagina’) definisce il titolo che poi viene visualizzato dalla pagina master mediante la direttiva @yield(‘title’). Seguono le sezioni contenenti la sidebar e la sezione @section(‘content’) che verrà richiamata dalla pagina master grazie alla direttiva @yield(‘content’).
Da notare che la @section(sidebar) utilizza @parent per richiamare i contenuti già definiti nella pagina master. Occorre precisare la differenza che intercorre quando una direttiva @section viene chiusa con @show, rispetto a quando la si chiude con @endsection, quando si usa @endsection la sezione viene semplicemente definita, mentre quando si utilizza @show la sezione viene visualizzata come quando si usa @yield.
COMPONENTS & SLOTS
Una caratteristica molto interessante ed utile offerta dal blade engine di Laravel è la possibilità di creare delle componenti riutilizzabili e facilmente richiamabili all’interno delle view:
Creiamo il file resources/views/alert.blade.php
<div class="alert alert-danger"> {{ $slot }} </div>
Il contenuto di questo file rappresenta una componente riutilizzabile all’interno di una view, la variabile $slot sarà sostituita di volta in volta dal contenuto specificato, come si può vedere di seguito:
File resources/views/testcomponente.blade.php
@extends('layout.app') @section('title', 'Modulo prova jquery') @section('content') <div class="row"> <div class="offset-md-3 col-md-6 col-xs-12"> @component('alert') Attenzione, Attenzione!!! @endcomponent </div> </div> @endsection
Talvolta all’interno della componente potrebbero essere necessari più placeholders ad esempio:
<div class="alert alert-danger"> <h1>{{ $title }}</h1> {{ $slot }} </div>
Si può notare la presenza del segnaposto {{ $title }}, ecco come utilizzare componenti con questa caratteristica aggiuntiva:
@extends('layout.app') @section('title', 'Modulo prova jquery') @section('content') <div class="row"> <div class="offset-md-3 col-md-6 col-xs-12"> @component('alert') @slot('title') Titolo componente @endslot Attenzione, Attenzione!! @endcomponent </div> </div> @endsection
Quando si richiama una componente, le si possono passare delle variabili, ecco come:
@component('test.alert',['nome' => 'Francesco']) @slot('title') Titolo componente @endslot Attenzione, Attenzione {{$nome}} @endcomponent
VISUALIZZARE I DATI
In parte lo abbiamo già visto, per visualizzare i dati passati alle views è sufficiente racchiudere i nomi delle variabili all’interno di una doppia parentesi graffa:
Ciao, {{ $nome }}
L’ora corrente è {{ time() }}
La doppia parentesi graffa applica alla variabile la funzione PHP htmlspecialchars per evitare attacchi di tipo XSS. Se si vuole evitare il filtro di htmlspecialchars è sufficiente usare la sintassi seguente:
Ciao, {!! $nome !!}.
STRUTTURE DI CONTROLLO
Il blade template, oltre all’ereditarietà ed alle componenti, offre un’efficace insieme di strutture di controllo (selezione, loop ecc) simili a quelle offerte da php.
Passiamole in rasegna:
@if….@endif
@if (count($records) === 1) <p class=”alert alert-info”>Un record trovato</p> @elseif (count($records) > 1) <p class=”alert alert-info”>{{ $records }} record trovati</p> @else <p class=”alert alert-info”>Nessun record trovato</p> @endif
@unless
@unless (Auth::check()) You are not signed in. @endunless
Questo codice viene eseguito se la condizione Auth::check() restituisce false (Auth::check() verifica se vi è un utente loggato, restituendo true se lo è)
@isset
Questa direttiva è la controparte di isset() di php
@isset($records) <p>Variabile definita</p> @endisset
@empty controparte della funzione php empty()
@empty($records) <p>La variabile è vuota</p> @endempty
@auth e @guest
@auth e @guest verificano se l’utente è autenticato (la prima) se non lo è la seconda.
@auth <p> Utente loggato</p> @endauth @guest <p>Non sei loggato</p> @endguest
@hasSection, questa direttiva verifica se una sezione possiede contenuti
@hasSection('navigation') <div class="text-right"> @yield('navigation') </div> <div class="clearfix"></div> @endsection
@switch ….@endswitch
@switch($i) @case(1) Primo... @break @case(2) Secondo... @break @default Default …... @endswitch
Loops
@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 @foreach ($users as $user) @if ($user->type == 1) @continue @endif <li>{{ $user->name }}</li> @if ($user->number == 5) @break @endif @endforeach
Caratteristica molto comoda del blade engine è quella di usare le condizioni in un’unica riga come mostrato nell’esempio seguente:
@foreach ($users as $user) @continue($user->type == 1) // se è vera la condizione salta all'iterazione successiva <li>{{ $user->name }}</li> @break($user->number == 5) // se è vera la condizione esce dal ciclo @endforeach
Durante il loop si ha la possibilità di usare la variabile $loop, che fornisce accesso ad alcune informazioni relative al ciclo in esecuzione (se è la prima iterazione, se è l’ultima, il numero totale di iterazioni, se è un’iterazione di indice pari o dispari ecc.)
@foreach ($users as $user) @if ($loop->first) This is the first iteration. @endif @if ($loop->last) This is the last iteration. @endif <p>This is user {{ $user->id }}</p> @endforeach
Vi è la possibilità di accedere da un loop annidato alle informazioni del padre, come di seguito mostrato:
@foreach ($users as $user) @foreach ($user->posts as $post) @if ($loop->parent->first) This is first iteration of the parent loop. @endif @endforeach @endforeach
Ecco un elenco di tutte le proprietà della variabile $loop:
Proprietà | Descrizione |
$loop->index | Indice dell’iterazione corrente (parte da 0). |
$loop->iteration | Numero iterazione (inizia da 1). |
$loop->remaining | Quante iterazioni rimangono. |
$loop->count | Numero totale di iterazioni. |
$loop->first | Vero se è la prima iterazione. |
$loop->last | Vero se è l’ultima iterazione. |
$loop->even | Vero se è un’iterazione di indice pari. |
$loop->odd | Vero se è un’iterazione di indice dispari. |
$loop->depth | Livello di annidamento del loop. |
$loop->parent | Variabile loop del genitore (si applica ad un loop figlio). |
Inserire un commento in una view blade:
{{– Semplice commento –}}
Se si desidera usare del codice php puro, può essere molto comodo farlo utilizzando la direttiva @php … @endphp, invece di <?php …. ?>
@php Codice php @endphp
CSRF e SPOOFING DEI METODI NEI MODULI
Quando in una blade view si crea una form, per scongiurare gli attacchi CSRF (cross site request forgery), laravel utilizza un campo nascosto _token che viene verificato dal middleware predisposto per la protezione da attacchi csrf.
Il suddetto campo viene così definito:
<input name=”_token” type=”hidden” value=”{!! csrf_token() !!}” />
Ebbene, anche in questo il blade engine rende le cose molto più semplici, infatti per generare un tale campo è sufficiente utilizzare la direttiva @csrf, come di seguito indicato
<form method="POST" action="/profile"> @csrf ... </form>
Un’altra feature veramente utile, offerta dal blade engine, è quella che permette di fare lo spoofing del metodo di invio del modulo. Per cambiare il metodo di invio è sufficiente utilizzare la direttiva @method(‘nome metodo’), esempio:
<form action="/foo/bar" method="POST"> @method('PUT') ... </form>
Nell’esempio appena visto, il metodo di invio dei dati del modulo sarà PUT e non post. Se si volesse usare il metodo DELETE, sarebbe sufficiente fare così:
<form action="/foo/bar" method="POST"> @method('DELETE') ... </form>
Validazione form e visualizzazione degli errori
La direttiva @error(‘nome campo’)…@enderror permette di mostrare o includere contenuti solo nel caso in cui, durante la validazione dei dati del modulo, si sono riscontrati per il campo passato come argomento, violazioni delle regole.
<label for="title">Linux kernel</label> <input id="title" type="text" class="@error('title') is-invalid @enderror"> @error('title') <div class="alert alert-danger">{{ $message }}</div> @enderror
L’esempio non ha bisogno di spiegazioni, ma mostra la potenza e la versatilità di questa direttiva.
INCLUDERE SUB-VIEW
Mediante la direttiva @include, è possibile includere una sub-view all’interno di una view, tutte le variabili della view principale sono visibili anche nella sub-view.
<div> @include('errors') <form> <!—contenuti del form --> </form> </div>
Nonostante la view erediti le variabili dalla principale, è possibile passarne altre utilizzando il secondo parametro della direttiva @include():
@include(‘nomeview’, [‘key’ => ‘value’])
Se si cerca di includere una view che non esiste, laravel lancia un’eccezione. Per evitare la segnalazione di errori, è posibile usare @includeIf():
@includeIf(‘nomeview’, [‘key’ => ‘value’])
Utilizzando @includeIf(), se la view non esiste il programma continua normalmente la sua esecuzione.
Se l’inclusione di una view dipende dal verificarsi di una condizione, allora è possibile utilizzare @includeWhen():
@includeWhen($boolean, ‘nomeview’, [‘key’ => ‘value’])
Se si desidera includere la prima view esistente tra un elenco, allora occorre usare @includeFirst()
@includeFirst([‘custom.admin’, ‘admin’], [‘some’ => ‘data’])
Utilizzare una view all’interno di un ciclo
Supponiamo di avere una collection o un array che elenca un insieme di opzioni e di voler creare una lista simile alla seguente:
<ul> <li>Opzione 1 </li> <li>Opzione 2 </li> <li>Opzione 3 </li> . . <li>Opzione n </li> </ul>
Utilizzando la direttiva @each() tutto diventa molto più semplice, infatti è sufficiente creare una partial view opzioni.blade.php con il contenuto seguente:
<li>{{$opzione}}</li>
mentre nella view principale va usato il codice seguente:
<ul> @each(‘opzioni’,$colletion_opzioni,’opzione’) </ul>
I parametri passati hanno il seguente significato:
‘opzioni’ -> nome della view, $colletion_opzioni -> contiene l’elenco delle opzioni, ‘opzione’ -> nome della variabile che conterrà ad ogni ciclo l’opzione corrente. Volendo, è possibile usare un quarto parametro contenente il nome della view da utilizzare se la variabile $colletion_opzioni è vuota.
Di seguito un esempio completo sull’uso della direttiva @each():
Nel file routes/web.php creare la seguente route
Route::get('/testsubview',function() { $opts = ['opzione 1','opzione 2','opzione 3','opzione 4',]; return view('test.testsubview',['opts' => $opts]); });
Creare poi in resources/views/test la view testsubview.blade.php con il seguente contenuto
<div> <h1>Test sub-view</h1> <ul> @each('test.opzioni',$opts,'opt') </ul> </div>
Infine creare in resources/views/test la partial view opzioni.blade.php con il seguente contenuto
<li>{{ $opt }}</li>
A questo punto se puntiamo il browser su http://laraapp.webserver.loc/testsubview , comparirà il nostro elenco puntato:
Test sub-view
- opzione 1
- opzione 2
- opzione 3
- opzione 4
Chiudiamo questo articolo informando che laravel dà la possibilità di creare direttive personalizzate, per ulteriori approfondimenti consultare la guida ufficiale (https://laravel.com/docs/5.8/blade#extending-blade )
Articoli correlati