Come utilizzare al meglio Laravel ed Eloquent

Pubblicato 5 months ago ・ 5 mins read
Guida Laravel
IMPORTANTE

La guida a Laravel 7 sta arrivando!

Laravel per Tutti sarà presto disponibile.

Resta in contatto, scegli tu il modo.


Ho deciso di aggiornare un mio vecchio articolo pubblicato sull'ormai defunto medium.com e adattarlo alla nuova versione di Laravel 7

Troverai alcune scorciatoie sempre valide e nuovi helper stratosferici per la gestione delle stringhe.

Cosa aspetti? Buona pratica!

1. Doppia condizione Where

Ti sarà sicuramente capitato di dover selezionare dalla tabella l'utente con nome Mario e cognome Rossi:

# Query SQL  
SELECT * FROM `utenti`
    WHERE
        `nome` = 'Mario'
        AND `cognome` = 'Rossi'
    LIMIT 1

Utilizzando la sintassi del query builder di Laravel ti ritroveresti con questa porzione di codice:

// Un esempio potrebbe essere:
User::where("nome", 'Mario')->where("cognome", 'Rossi')->first();

// oppure anche:
User::where(["nome" => 'Mario', "cognome", 'Rossi'])->first();

Ecco invece un esempio di Clean code con laravel:

//Utilizzando AND:
User::whereNomeAndCognome('Mario','Rossi')->first();

//Con la stessa logica possiamo utilizzare anche OR:
User::whereNomeOrCognome('Mario','Rossi')->get();

2. Relazione belongsTo con valore di default

Realizzare un sistema per gestire i commenti di un blog è una pratica comune. Voglio analizzare con te un caso d'uso specifico: in caso di un commento di un utente "ospite" come gestire l'assenza dell'username?

Prova ad utilizzare la seguente sintassi:

//Funzione per gestire la relazione nel Model
public function user()
{
    return $this->belongsTo('App\User')->withDefault([
        'name' => 'Utente Anonimo',
    ]);
}

3. Redirect dal web.php

Ho visto alcuni progetti Laravel (piuttosto grandi) organizzati con un RedirectController apposito per la gestione degli url: un bagno di sangue.

Esiste un particolare metodo che ti permetterà di farlo direttamente nel file delle routes:

// Tutti gli utenti che atterreranno su /prodotto-esaurito verranno reindirizzati su /prodotto-disponibile
Route::redirect('/prodotto-esaurito','/prodotto-disponibile',301);

4. Eliminare controller inutili

Hai una pagina statica "Chi sono", tutto il contenuto è presente nella view e nessuna variabile è istanziata nel controller. Praticamente sto parlando di questo caso particolare:

//Funzione nel controller relativo
public function about()
{  
    return view('about'); 
}

Se il tuo controller è davvero semplice e restituisce una vista, dovresti utilizzare il metodo apposito per le view:

//Ad esempio all'url home, richiamiamo la view index
Route::view('/home','homepage.index');

E, se proprio hai necessità di passare dei parametri puoi utilizzare:

//Ecco come passare un titile 
Route::view('/home','homepage.index', ['title' => 'Chi sono']);

5. Crea il tuo menù dinamico

Un annoso problema è quello della gestione dei menù dinamici: la corretta applicazione della classe 'active'.

Lo step preliminare è quello di assegnare un nome a tutte le route. Utilizzare una variabile univoca ti permetterà di non incorrere in problemi di integrità dei dati nel caso l'url cambi.

//Esempio di una porzione di Route del file web.php
Route::view('/', 'homepage')->name('homepage');
Route::view('/about', 'about')->name('about'); 

Per gestire il menù invece dovrai utilizzare il request()->is(), in questo modo:

<!--Layout tipico per gestire un menù HTML -->
<ul>
    <li class="{{request()->is('home') ? 'active' : ''}}">Home</li>
    <li class="{{request()->is('about') ? 'active' : ''}}">About</li>
</ul>

Per gestire gli eventuali url padre-figlio, come nell'esempio:

// Extra route di secondo livello
Route::view('/about/info', 'aboutinfo')->name('about.info');

Puoi semplicemente usare il carattere jolly * sul "padre" about:

<!--Layout tipico per gestire un menù HTML -->

<ul>
    <li class="{{request()->is('home') ? 'active' : ''}}">Home</li>
    <li class="{{request()->is('about*') ? 'active' : ''}}">About</li>
</ul>


la classe active sarà così applicata automaticamente a tutti gli url contenuti in 'about'

6. Refactoring di Auth::user()->id

Scrivere ogni volta Auth::user()->id non è sbagliato, ma puoi scriverlo in un modo più performante:

//Primo metodo
Auth::id()

//Altro metodo utilizzando l'Helper auth()
auth()->id()

7. Ottimizzare la paginazione

Paginate o simplePaginate? La differenza c'è, ed è molto importante.

Come è facile intuire gli elementi della paginazione generati saranno diversi, in base al metodo utilizzato:

  • Il metodo paginate(n) leggerà TUTTI i record della tabella, calcolerà il numero massimo di pagine e lo dividerà per n così da generare i vari indici. Lato grafico, visualizzerà a video un elemento HTML con i tasti Avanti, Indietro e le varie pagine con i numerini come indice. Questo metodo, su database di grandi dimensioni, NON è una best practices in termini prestazionali.
  • Il metodo simplePaginate(n) si limiterà a leggere soltanto i primi n record inseriti. Lato grafico visualizzerà un elemento HTML con i tasti Avanti e Indietro. Il tasto avanti si occuperà di leggere i successivi n elementi.
// Richiamo il metodo paginate con n = 15
$users = Users::paginate(15);


// Richiamo il metodo DB::table() e successivamente la paginazione semplice con n = 15
$users = DB::table('users')->simplePaginate(15);


8. Mai più relazioni nulle

Utilizzando sempre l'esempio di un Blog, il caso d'uso in questione è la possibilità (non molto remota) che alcuni post non contengano commenti.

Come filtrare il tutto senza fare grossi giri con controlli o helper? 

Normalmente si potrebbe utilizzare una struttura del genere:

// Assegno alla variabile $postsWithComments il risultato di questa query, senza gestire errori
$postsWithComments = BlogPost::with("comments")->get();

Ma per gestire eventuali BlogPost senza commenti associati si dovrebbe creare una struttura nel controller o nella view (pessima idea!) per non generare errori 404.

Gli helper di Laravel ci aiutano in questo modo:

 $postsWithComments = BlogPost::with("comments")->has("comments")->get();

9. Lavora con le stringhe

Con Laravel 7 sono disponibili diversi metodi per manipolare le stringhe senza ricorrere alle funzioni PHP.

Prendendo come esempio questa stringa (spazi compresi, eh!):

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

Dovrai rendere questa stringa uno slug: rimuovere gli spazi, rimuovere i simboli, rendere tutto minuscolo, e cambiare Taylor con Francesco.

Con PHP:

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

Utilizzando gli helper di Laravel 7 invece:

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

10. Where Espressivo

Sempre rimanendo in tema di ottimizzazione del codice, è presente un piccolo trucchetto che renderà le tue query ancora più espressive.

//Classica query
$query = User::where('role', '=', 1)->get();

//Quey con uguaglianza sottintesa
$query = User::where('role', 1)->get();

//Query utilizzando il where<var>
$query = User::whereRole(1)->get();

Ovviamente questa cosa può essere utilizzata anche nel momento in cui si dovranno trattare dei campi timestamps in frontend.

$q->whereDate('created_at', date('Y-m-d'));
$q->whereDay('created_at', date('d'));
$q->whereMonth('created_at', date('m'));
$q->whereYear('created_at', date('Y'));





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.