Le novità di Laravel 7

Pubblicato 5 months ago ・ 11 mins read
IMPORTANTE

La guida a Laravel 7 sta arrivando!

Laravel per Tutti sarà presto disponibile.

Resta in contatto, scegli tu il modo.


Giunto ormai alla versione 7.* , Laravel continua a seguire il Leitmotiv degli ultimi anni: lo sviluppatore prima di tutto.

Tra le novità inserite: oltre ai cast standard di Eloquent è stata aggiunta la possibilità di creare dei cast personalizzati; sono stati introdotti 44 nuovi Helper di Fluent String per la gestione delle stringhe; un wrapper di guzzle che include un client HTTP minimale; Laravel Sanctum (ex Airlock) per la gestione dell'autenticazione senza ricorrere a JWT; nuovi comandi Artisan per i test PHPUnit; il supporto nativo al Cross-Origin Resource Sharing (CORS); l'inclusione di Blade X e ottimizzazioni atte a migliorare la stabilità e velocità (sistema di caching delle route fino a 2 volte più veloce!) delle applicazioni.

Potrai trovare tutto spiegato dettagliatamente sulle note di release sul sito ufficiale.

Diatriba Laravel Airlock: Un'azienda svizzera ha chiesto formalmente di cambiare nome al nuovo nato in caso Laravel, Airlock a quanto pare era un marchio registrato. Il buon Taylor Otwell ha così deciso di rinominare il package in Laravel Sanctum. Ecco il tweet:




La guida reltiva  all'upgrade segnala un tempo medio di 15 minuti per effettuare l'aggiornamento dalla 6.* alla 7.*. Se il tuo obiettivo è soltanto quello di provare la nuova versione, puoi creare un nuovo progetto utilizzando il create-project di composer:

composer create-project --prefer-dist laravel/laravel laravel7test

Ho provato la nuova release soffermandomi su quelle novità secondo me più interessanti e di immediato risultato. Ogni integrazione, segnalazione o appunto è ben accetta.

- ZTTP/HTTP Client

È stato inserito un sistema di API "minimale" per le funzionalità più utilizzate di Guzzle.

Potrai gestire gran parte delle chiamate HTTP in pieno stile Laravel con del codice pulito e chiaro.

Senza dover per forza stanziare Controller e View, apri semplicemente il file web.php e modifica la route dell'indirizzo '/' come segue (ricorda di importare la classe Http!):

routes/web.php

<?php

use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    return $response = Http::get('https://jsonplaceholder.typicode.com/todos/')->json();
});

Il risultato sarà un semplice Response in formato JSON.

Ovviamente ci sono altri helper da utilizzare per il metodo GET:

//Direttamente dalla documentazione ufficiale 

$response->status();
$response->ok(;
$response->successful();
$response->serverError(;
$response->clientError(;
$response->header($header);
$response->headers();

Per scoprire di più su questa nuova classe ti consiglio di leggere la documentazione ufficiale.

- Mail Markdown

Difficile fare meglio dell'attuale sistema di generazione mail di Laravel, per questo in laravel 7 si è puntato molto sul fronte del design.

Il template di default è stato disegnato completamente con Tailwindcss.

Genera una nuova classe Mail con il comando:

php artisan make:mail MailDiBenvenuto --markdown=emails.user.new

La prima parte genererà la classe di riferimento (io l'ho chiamata MailDiBenvenuto) la seconda invece andrà a creare la view new.blade.php in resources/views/emails/user/ .

Ecco i file appena creati:

app/Mail/MailDiBenvenuto.php

<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;

class MailDiBenvenuto extends Mailable
{
    use Queueable, SerializesModels;

    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->markdown('emails.user.new');
    }
}

e la view:

resources/views/emails/user/new.blade.php

@component('mail::message')
# Introduction

The body of your message.

@component('mail::button', ['url' => ''])
Button Text
@endcomponent

Thanks,<br>
{{ config('app.name') }}
@endcomponent

E se volessimo personalizzare il logo in alto senza modificare la struttura?

Dobbiamo accedere al vendor di riferimento senza intaccare il core. Lancia il comando:

php artisan vendor:publish

E digitare il numero corrispondete associato alla voce laravel-mail dalla lista.

Come risultato avrai una nuova cartella situata in:

resources/views/vendor/mail

Al suo interno troverai le cartelle HTML e Text. In base alle tue esigenze, andrai a modificare a tuo piacimento i testi o le immagini di default .

Per verificare l'anteprima della mail, puoi modificare la route principale come segue:

routes/web.php

Route::get('/', function () {
    return new MailDiBenvenuto();
});

Per scoprire di più su questa nuova classe ti consiglio di leggere la documentazione ufficiale.

- Blade X

Il package di Spatie chiamato spatie/laravel-blade-x è stato inserito in modo nativo in Laravel 7. Per chi non avesse mai usato il pacchetto (è ancora disponibile per la versione 5.8 e 6.*) Laravel Blade X ti permetteva di eseguire dei rendering dei componenti HTML e includerli direttamente nelle view blade.

Blade elaborerà così i componenti associati alle view e restituirà un semplice file HTML. Questo significa che non ci saranno problemi con quei framework javascript (Vuejs, React o Alpine.js) che utilizzano una sintassi simile a Blade X.

Il pacchetto è stato adattato e integrato al core di Laravel, potrai richiamare la classe direttamente dalla CLI Artisan.

Crea un nuovo progetto Laravel con:

composer create-project --prefer-dist laravel/laravel blog

Andremo a modificare la schermata di benvenuto rendendo la fascia relativa ai link, un componente. lancia il comando:

php artisan make:component link

Verranno generati due file: Link.php e link.blade.php.

Il primo file, Link.php, lo troverai in una nuova cartella generata all'interno di /app/. Di default ci saranno le funzioni __construct() e render(). Nulla di più. Per iniziare ad utilizzarlo, dovrai semplicemente dichiarare e inizializzare le variabili (ad esempio $name) all'interno di __construct() e automaticamente verrà effettuato il binding dei dati dichiarati nella view dichiarata nel render().

Essendoci diversi link, dobbiamo passare i dati al frontend. Come se stessi scrivendo all'interno di un controller, crea una nuova funzione list() con il return dell'array da stampare.

Ecco l'esempio completo appena descritto:

app/View/Components/Link.php

<?php

namespace App\View\Components;

use Illuminate\View\Component;

class link extends Component
{
    public $name;
    /**
     * Create a new component instance.
     *
     * @return void
     */
    public function __construct($name)
    {
        $this->name = $name;
    }

    /**
     * Get the view / contents that represent the component.
     *
     * @return \\Illuminate\\View\\View|string
     */
    public function render()
    {
        return view('components.link', [
            'list'=> $this->list()
        ]);
    }

    public function list(){
        return [
            ['name' => 'Docs', 'link' => 'https://laravel.com/docs'],
            ['name' => 'Laracasts', 'link' => 'https://laracasts.com'],
            ['name' => 'News', 'link' => 'https://laravel-news.com'],
            ['name' => 'Blog', 'link' => 'https://blog.laravel.com'],
            ['name' => 'Nova', 'link' => 'https://nova.laravel.com'],
            ['name' => 'Forge', 'link' => 'https://forge.laravel.com'],
            ['name' => 'Vapor', 'link' => 'https://vapor.laravel.com'],
            ['name' => 'GitHub', 'link' => 'https://github.com/laravel/laravel']
        ];
    }
}



resources/views/components/link.blade.php

<div class="title m-b-md">
    {{$name}}
</div>

<div class="links">
    @foreach($list as $li)
        <a href="{{$li['link']}}">{{$li['name']}}</a>
    @endforeach
</div>


Adesso non ti resta che modificare il body della view:

resources/views/welcome.blade.php

...
...
<body>
        <div class="flex-center position-ref full-height">
            @if (Route::has('login'))
                <div class="top-right links">
                    @auth
                        <a href="{{ url('/home') }}">Home</a>
                    @else
                        <a href="{{ route('login') }}">Login</a>

                        @if (Route::has('register'))
                            <a href="{{ route('register') }}">Register</a>
                        @endif
                    @endauth
                </div>
            @endif

            <div class="content">
                <x-link name="Francesco Mansi"/>
            </div>
        </div>
    </body>
...
...***

Variabili e Merge

Interessante è anche la gestione delle variabile e dei vari attributi.

Ipotizziamo di voler rendere il name dinamico e passare una classe tra due componenti.

resources/views/welcome.blade.php

...
...
<x-link :name="config('app.name')" class="m-b-md"/>
...
...

Negli esempi precedenti, name era una semplice assegnazione. I due punti all'inizio indicano all'Engine-Blade che il contenuto all'interno è una variabile PHP. Le doppie parentesi non saranno più necessarie.

Per trasportare tutti gli attributi non dinamici attraverso i livelli, invece, dovrai utilizzare la variabile {{$attributes}} all'interno del componente child.

Una sorta di BUS che si occuperà del trasporto dei dati.

resources/views/components/link.blade.php

<div class="title m-b-md">
    {{$name}}
</div>

<div class="links" {{$attributes}} >
    @foreach($list as $li)
        <a href="{{$li['link']}}">{{$li['name']}}</a>
    @endforeach
</div>

Ma c'è un problema. All'interno del div c'è già un attributo class. Niente paura.

Utilizzeremo la funzione merge().

La variabile $attributes è un array con all'interno la keys "class" e tutti i valori associati (nel nostro caso solamente la classe "m-b-md"). Non dovremo fare altro che aggiungere all'array in questione una nuova voce, facendo attenzione a dichiarare correttamente la keys "class" e impostando il valore "links".

In questo modo:

resources/views/components/link.blade.php
...
...
<div {{$attributes->merge(['class'=>'links'])}} >
...
...

Il risultato sarà che una volta renderizzata la pagina HTML, tutto questo magistero si tramuterà in un semplicissimo:

<div class="links m-b-md">


Componente inline

Esiste anche una configurazione più semplice che consiste nel generare un unico file in app/View/Components con la funzione render() che non andrà a richiamare una view, ma stamperà direttamente il contenuto.

Lancia il comando:

php artisan make:component Banner --inline

Verrà generato il file Banner.php, con la stessa struttura del precedente ma con l'unica differenza che il contenuto della view sarà incluso all'interno dei tag Blade:

<<<'blade'
...
...
blade;

Un ottimo modo per gestire Alert, Banner o elementi grafici non troppo complessi.

app/View/Components/Banner.php

<?php

namespace App\View\Components;

use Illuminate\View\Component;

class Banner extends Component
{
    /**
     * Create a new component instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Get the view / contents that represent the component.
     *
     * @return \\Illuminate\\View\\View|string
     */
    public function render()
    {
        return <<<'blade'
<div>
Francesco Mansi
</div>
blade;
    }
}

Aggiungi il nuovo componente appena creato nella view:

resources/views/welcome.blade.php

...
...
<div class="content">
        <x-link :name="config('app.name')" class="m-b-md"/>
        <x-banner/>
</div>
...
...

Auto-discovery

L'ultimo metodo disponibile è simile alla logica già utilizzata per le pagine di errore custom.

Crea una nuova view (dal contenuto molto semplice) in resources/views/components/partials chiamandola, ad esempio, footer.blade.php:

resources/views/components/footer.blade.php

<div>
   <p>Footer</p>
</div>

Potrai richiamare direttamente il componente come hai gia fatto nei due precedenti modi:

resources/views/welcome.blade.php

...
...
<div class="content">
        <x-link :name="config('app.name')" class="m-b-md"/>
        <x-banner/>
				<x-footer/>
</div>
...
...

Per scoprire di più su questa nuova classe ti consiglio di leggere la documentazione ufficiale.

- Laravel Sanctum (ex Airlock)

Laravel Sanctum nasce come opzione per autenticare i tuoi utenti senza dover implementare un sistema robusto OAuth2.

Sanctum è perfetto per tutte quelle web-app il cui frontend è alimentato da un sistema di API ospitato dallo stesso dominio.

Con Sanctum, puoi autenticare ogni richiesta attraverso un semplice middleware via HTTP.

Il tuo frontend effettuerà una richiesta POST all'indirizzo di login e, se le credenziali risulteranno corrette, Laravel memorizzerà una sessione contenente l'ID utente che verrà utilizzato per autenticare tutte le richieste future.

Innanzitutto installa il package da composer:

composer require laravel/sanctum

Successivamente, installa il ServiceProvider di Sanctum digitando:

php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"

Verrà generato il file sanctum.php in /config e verrà sostituita l'intera cartella migration con le nuove tabelle che andranno a contenere i personal access token degli utenti.

Per rendere il package operativo, non ti resta che lanciare le migrations con il comando:

php artisan migrate

Ricorda: se il tuo progetto è una SPA (Single Page Application) ricordati di aggiungere la classe EnsureFrontendRequestsAreStateful in api.

use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;

'api' => [
    EnsureFrontendRequestsAreStateful::class,
    'throttle:60,1',
    \\Illuminate\\Routing\\Middleware\\SubstituteBindings::class,
],

Per scoprire di più su questa nuova classe ti consiglio di leggere la documentazione ufficiale.

- Fluent Strings

Migliorare l'esperienza di sviluppo è uno dei capisaldi di Laravel. Con la versione 7 questo concetto viene esaltato ancora di più.

Destreggiarsi tra le varie funzioni PHP per la formattazione di stringhe( trim(), explode(), str_replace(), strlower() ecc...) è un'operazione da non augurare nemmeno al nostro peggior nemico.

Con Laravel 7 sono stati implementati circa 44 nuovi Helper direttamente nella libreria Illuminate\Support\Str.

Trasformeranno i tuoi tentativi di formattazione in attimi di puro divertimento.

Ti permetteranno di eseguire le stesse operazioni che avresti fatto concatenando le funzioni di PHP ma utilizzando la classica Arrow-Syntax. Eccoti un esempio:

//Dato iniziale
$stringa ='      Buon Compleanno Taylor!       ';


#PHP
strtolower(str_replace('Taylor', 'Francesco', trim(preg_replace('/[^A-Za-z0-9-]+/', '-', $stringa), '-')));

#Laravel
Str::of($stringa)
     ->trim()
     ->replace('Taylor', 'Francesco')
     ->slug()
		 ->lower();

//Dato Finale => 'buon-compleanno-francesco'

Per scoprire di più su questa nuova classe ti consiglio di leggere la documentazione ufficiale.

- Stub Personalizzati

La CLI Artisan offre, da sempre, la possibilità di generare qualsiasi elemento digitando un semplice comando:

....

php artisan make:model [name]
php artisan make:controller [name]
php artisan make:middleware [name]
php artisan make:migration [name]
php artisan make:request [name]

....

Con Laravel 7 è stata inserita la possibilità di modificare la struttura di queste classi, senza andare ad intaccare il core del Framework, utilizzando i già noti Stub.

Lancia il comando Artisan:

php artisan stub:publish       

Verrà creata una nuova directory chiamata Stubs nella root principale del progetto. All'interno troverai tutte classi disponibili in formato .stub.

Al momento sono 17 stub:

- Controller.api.stub
- Controller.invokable.stub
- Controller.model.api.stub
- Controller.model.stub
- Controller.nestead.api.stub
- Controller.nestead.stub
- Controller.plain.stub
- Controller.stub
- Job.queued.stub
- Job.stub
- Migration.create.stub
- Migration.stub
- Migration.update.stub
- Model.pivot.stub
- Model.stub
- Test.stub
- Test.unit.stub

Proviamo a modificare il template di un controller.

Lancia il comando:

php artisan make:controller DefaultController

Avrai come risultato un nuovo controller chiamato DefaultController.php situato in app/Http/Controllers/ con il seguente contenuto:

<?php
    
    namespace App\Http\Controllers;
    
    use App\Http\Controllers\Controller;
    use Illuminate\Http\Request;
    
    class DefaultController extends Controller
    {
       // 
    }

Adesso apri il file controller.plain.stub situato nella cartella Stubs ****e osserva il contenuto.

<?php

namespace {{ namespace }};

use {{ rootNamespace }}Http\Controllers\Controller;
use Illuminate\Http\Request;


class {{ class }} extends Controller
{
    //
}

Questa è la configurazione base di un Controller. I placeholder contenuti nelle parentesi graffe non sono altro che percorsi o variabili generate dinamicamente.

Supponiamo ora di voler aggiungere ad ogni controller del nostro progetto la classe Illuminate\Support\Str.

Basterà aggiungere il percorso in questo modo:

<?php

namespace {{ namespace }};

use {{ rootNamespace }}Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Str;

class {{ class }} extends Controller
{
		//
}

Infine, lancia il comando Artisan per generare un nuovo controller, questa volta lo chiamerai EditedController:

php artisan make:controller EditedController

Il file generato conterrà in modo nativo la libreria scelta:

<?php
    
    namespace App\Http\Controllers;
    
    use App\Http\Controllers\Controller;
    use Illuminate\Http\Request;
		use Illuminate\Support\Str;
    
    class EditedController extends Controller
    {
			// 
    }

Per scoprire di più su questa nuova classe ti consiglio di leggere la documentazione ufficiale.

Scopri di più su Laravel 7

Come detto ad inizio articolo, queste sono solo alcune delle nuove funzionalità di Laravel 7. Potrai trovare tutto spiegato dettagliatamente sulla documentazione ufficiale.


IMPORTANTE

La guida a Laravel 7 sta arrivando!

Laravel per Tutti sarà presto disponibile.

Resta in contatto, scegli tu il modo.

© 2020 Francesco Mansi

Questo sito utilizza cookie tecnici per migliorare l'esperienza utente.