CONTATTACI

Guide per aspiranti programmatori

Lezione 19 / 30

Eloquent e Models

Con il termine ORM (Object Relational Mapper) si intende una tecnica di programmazione informatica che permette, nella pratica, di mettere in relazione un database relazionale e un oggetto/classe nel proprio codice.

In Laravel viene fornito l’ORM Eloquent e si basa sulla corrispondenza tra una tabella del database e una classe di tipo “Model”. Nello specifico, implementazione ORM di Eloquent è del tipo “Active Record”: una tabella sul database corrisponde ad una classe PHP e una singola riga della tabella corrisponde ad una istanza della classe.

L’utilizzo di Eloquent e dei Model semplifica molto l’interazione con il database, eliminando, in molti casi, la necessità di scrivere query dedicate.

Creare un model in Laravel

Il collegamento tra tabella e classe con Eloquent è realizzato utilizzando una convenzione sui rispettivi nomi. La classe del modello è indicata al singolare, la tabella collegata al plurale.

È, ovviamente, disponibile un comando Artisan per creare un nuovo modello, make:model, che supporta varie opzioni per creare anche altre classi collegate al model (controller, form, …). Quello che, sicuramente, ci interessa è creare un nuovo modello con l’annessa migrazione, per creare, quindi, automaticamente anche la nuova tabella (opzione -m).

$ php artisan make:model Post -m   

 INFO Model [app/Models/Post.php] created successfully.

 INFO Migration [database/migrations/2023_01_24_211341_create_posts_table.php] created successfully.
// in app/Models/Post.php
class Post extends Model
{
  use HasFactory;
}

// database/migrations/2023_01_24_181341_create_posts_table.php
// ...
  public function up()
  {
    Schema::create('posts', function (Blueprint $table) {
      $table->id();
      $table->timestamps();
    });
  }
// ...

Alla classe Post è, quindi, collegata e collegabile la tabella posts. Prima di eseguire la migrazione per creare la tabella, aggiungiamo qualche colonna d’esempio al metodo up della migrazione stessa. Non tocchiamo la classe App\Model\Post.

$table->tinyText('title');
$table->enum('status', ['draft', 'published', 'retired'])->default('draft')
$table->timestamp('published_at')->nullable();

Utilizzare un model

Senza ulteriori modifiche al nostro codice, in ogni punto della nostra applicazione Laravel, sarà possibile interagire con la classe Post nei modi opportuni per interagire, di fatto, con la tabella nel database.

// da qualche parte nella nostra app Laravel ...

$post = new App\Model\Post;

$post->title = "Another Post Bites the Dust";
$post->save();

$status = $post->status; // 'draft', il valore di default della colonna sul database
$id = $post->id; // generato automaticamente

$post->status = 'published';
$post->published_at = now();

$post->save()

$post->status = "foo"
$post->save() // genera una Illuminate\Database\QueryException

Notare in particolare che:

  • possiamo creare istanze della classe ($post) ed eseguire su di esse metodi della classe Model (->save()) che hanno effetto sul database, creando o modificando una riga
  • possiamo accedere alla colonne della riga tramite attributi dell’istanza che non abbiamo mai definito, ma che Eloquent crea dando loro gli stessi nomi della corrispettiva colonna (status, published_at)
  • al salvataggio della istanza su tabella, vengono accettati solo valori ammessi dalla colonna

NOTA: è possibile visualizzare gli attributi del proprio modello tramite il comando Artisan php artisan model:show <NOME_MODELLO>

Il nostro modello Post estende la classe astratta Model di Eloquent e da essa riceve molti(ssimi) metodi che ci permettono di interagire con i dati sul database senza dover scrivere alcuna riga di codice.

Oltre, quindi, ai metodi che operano sulla singola istanza/riga, da Model vengono ereditati metodi statici che operano sulla tabella collegata. Questo grazie all’ implementazione “Active Record” citata all’inizio.

// restituisce la riga della tabella `posts` con `id=10`
$anotherPost = Post::find(10);

// restituisce tutte le righe della tabella `posts`
$posts = Post::all();

// crea query tramite il builder e recupera le righe che corrispondono
$thisYearPosts = Post::where('status', 'published')
          ->where('published_at', '>=', '2022-12-31')
          ->get()

I vari metodi statici del model restituiscono istanze della classe quando servono recuperate singole righe (per esempio find) oppure istanze della classe Illuminate\Database\Eloquent\Collection nel caso di metodi che intendono recuperare array di righe.
Laravel mette a disposizione la classe Illuminate\Support\Collection come wrapper per interagire in modo agevole con gli
array PHP. La specifica classe per Eloquent estende la classe di base con metodi espressamente dedicati per i model.

Convenzioni e funzionalità dei modelli Eloquent in Laravel

Per comodità, riportiamo le principali convenzioni di Eloquent riguardanti i model.

  • la classe ha il nome della “risorsa” al singolare (es. FavoritePost)
  • la tabella ha lo stesso nome al plurale e in “snake case” (es. favorite_posts)
  • la colonna chiave primaria si chiama id, è un intero con autoincrement
  • esistono le colonne created_at e updated_at di tipo “timestamp”

È possibile, quindi, creare modelli Eloquent che possono collegarsi a tabelle che non rispettano queste convenzioni, indicando nella classe del model opportune property protected.

// in app/Models/Post.php posso indicare cosa non segue la convezione dei Model

class Post extends Model
{
  // il nome della tabella
  protected $table = 'post_table';

  // il nome della colonna primary key
  protected $primaryKey = 'post_id';

  // la colonna primary key non è auto-increment
  public $incrementing = false;

  // la colonna primary key non è di tipo intero
  protected $keyType = 'string';

  // ... cfr Illuminate\Database\Eloquent\Model per altre property
}

È anche possibile attivare particolari funzionalità in un Model, come ad esempio la “soft delete” o l’hidden di determinate colonne.

Con soft delete in Laravel si intende un’operazione che invece di rimuovere una riga da una tabella (hard delete), la contrassegna come non più disponibile. Attivare la soft delete su un Model Eloquent richiede uno sforzo minimo:

// nella `up` della migrazione va dichiarato che è una tabella "soft delete"
// viene in pratica aggiunta una colonna `deleted_at`
$table->softDeletes();

// nella classe del Model dichiaro che il model usa le soft delete
{
  use SoftDeletes;
  // ...
}

// nel codice dell'app, si continua a usare il metodo standard per rimuovere un record
$post = Post::find(44531);
$post->delete();

// che non comparirà nelle varie richieste
$activePosts = Post::all();

// ma sarà comunque recuperabile tramite metodi dedicati
$softDeletedPosts = Post::::onlyTrashed()->get();

La funzionalità di hidden delle colonne è invece utile nel caso in cui si voglia evitare che i valori di determinate colonne vengano inclusi nella istanza recuperata dal database. Le motivazioni per questa scelta sono le più disparate; l’esempio più immediato ci viene dal Model presente nelle classi fornite direttamente da Laravel quando si crea una nuova applicazione con Composer.

class User extends Model
{
  protected $hidden = [
    'password',
  ];
  // ...
}

La tabella degli utenti include informazioni sui singoli utenti registati, il model può essere recuperato tali informazioni e farle arrivare ad una view user.profile, ma non vogliamo di certo che l’attuale password dell’utente arrivi, anche se cifrata, fino a una view.

L’attributo $hidden permette di elencare le colonne che, seppure presenti e valorizzate sul database, non verranno incluse come property dell’istanza del model. Ovviamente, sarà possibile accedervi tramite opportuni metodi della classe Model

Contattaci senza impegno per informazioni sul corso

Pagamento rateale

Valore della rata: A PARTIRE DA 115 €/mese.

Esempio di finanziamento 

Importo finanziato: € 2440 in 24 rate da € 115 – TAN fisso 9,55% TAEG 12,57% – importo totale del credito € 2841.

Il costo totale del credito comprende: interessi calcolati al TAN indicato, oneri fiscali (imposta di bollo sul contratto 16,00 euro*) addebitati sulla prima rata, costo mensile di gestione pratica € 3,90, spesa di istruttoria € 0,00, spesa per invio rendicontazione periodica cartacea € 0,98 (o spesa per invio rendicontazione periodica cartacea € 0,00), imposta di bollo su rendicontazione periodica € 0,00. Modalità di rimborso obbligatoria: addebito diretto su c/c. La scadenza delle rate è determinata dal giorno della liquidazione del contratto; la data di scadenza delle rate è prevista il giorno 15 del mese. L’importo di ciascuna rata comprende una quota di capitale crescente e interessi decrescente secondo un piano di ammortamento “alla francese”. Offerta valida dal 01/01/2024 al 31/12/2024.

Messaggio pubblicitario con finalità promozionale. Per le informazioni precontrattuali richiedere sul punto vendita il documento “Informazioni europee di base sul credito ai consumatori” (SECCI) e copia del testo contrattuale. Salvo approvazione di Sella Personal Credit S.p.A. Aulab S.r.l. opera quale intermediario del credito NON in esclusiva.

*In fase di richiesta del finanziamento verrà proposta la facoltà di selezionare, in alternativa all’imposta di bollo sul contratto di 16,00 euro, l’imposta sostitutiva, pari allo 0,25% dell’importo finanziato.

Pagamento rateale

Valore della rata: A PARTIRE DA 210 €/mese.

Esempio di finanziamento  

Importo finanziato: € 4500 in 24 rate da € 210,03 – TAN fisso 9,68% TAEG 11,97% – importo totale del credito € 5146,55.

Il costo totale del credito comprende: interessi calcolati al TAN indicato, oneri fiscali (imposta di bollo sul contratto 16,00 euro*) addebitati sulla prima rata, costo mensile di gestione pratica € 3,90, spesa di istruttoria € 0,00, spesa per invio rendicontazione periodica cartacea € 0,98 (o spesa per invio rendicontazione periodica cartacea € 0,00), imposta di bollo su rendicontazione periodica € 0,00. Modalità di rimborso obbligatoria: addebito diretto su c/c. La scadenza delle rate è determinata dal giorno della liquidazione del contratto; la data di scadenza delle rate è prevista il giorno 15 del mese. L’importo di ciascuna rata comprende una quota di capitale crescente e interessi decrescente secondo un piano di ammortamento “alla francese”. Offerta valida dal 01/01/2024 al 31/12/2024.

Messaggio pubblicitario con finalità promozionale. Per le informazioni precontrattuali richiedere sul punto vendita il documento “Informazioni europee di base sul credito ai consumatori” (SECCI) e copia del testo contrattuale. Salvo approvazione di Sella Personal Credit S.p.A. Aulab S.r.l. opera quale intermediario del credito NON in esclusiva.

* In fase di richiesta del finanziamento verrà proposta la facoltà di selezionare, in alternativa all’imposta di bollo sul contratto di 16,00 euro, l’imposta sostitutiva, pari allo 0,25% dell’importo finanziato.

Contattaci senza impegno per informazioni sul corso

Scopriamo insieme se i nostri corsi fanno per te. Compila il form e aspetta la chiamata di uno dei nostri consulenti.