Come utilizzare al meglio Laravel ed Eloquent

Come utilizzare laravel
Ultimo Aggiornamento 11 mesi fa

sponsor

Laravel per Tutti disponibile ora.

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'));




Altri Articoli Correlati