Uno dei motivi per cui usare Laravel per la propria applicazione web è anche la versatilità e la semplicità con cui è possibile interagire con uno dei database supportati.
Difficile, infatti, immaginare una applicazione web moderna che non debba interagire con una base dati. Laravel offre agli sviluppatori php diversi approcci, a seconda della necessità, che partono dall’esecuzione diretta di codice SQL, passano per la costruzione di query tramite builder, fino ad arrivare al sistema ORM Eloquent.
Al momento della stesura di questa guida, Laravel (9.x) supporta i seguenti database:
- MariaDB 10.3+
- MySQL 5.7+
- PostgreSQL 10.0+
- SQL Server 2017+
- SQLite 3.8.8+
Database relazionali
Con database management systems (DBMS) si intende un programma che consente di interagire con un database: scrivere dati, eseguire query, eseguire altri task relativi alla gestione di un database. Per consentire queste interazioni, il DBMS rende disponibile un suo modello interno che definisce come il DBMS stesso organizza i dati memorizzati.
Il modello relazionale è un modo di organizzazione dei dati più comune e diffuso nei DBMS, nonché il primo pensato negli anni ’60.
L’elemento fondamentale del modello relazione sono le relazioni, che nei RDMBS (Relational DBMS) moderni vengono indicate come tabelle. Una relazione è un set di tuple – o righe in una tabella – in cui ciascuna tupla condivide un insieme di attributi – o colonne.
Database – Relazioni
Una colonna è la struttura organizzativa più piccola di un database relazionale; ogni colonna rappresenta un aspetto che definisce i record nella tabella. Alla creazione di una colonna in una tabella viene indicato anche il tipo di dato, che definisce il tipo di voce consentito nella colonna.
Nei database relazionali, ogni tabella contiene almeno una colonna utilizzabile per identificare in modo univoco ogni riga. Tale colonna costituisce la chiave primaria.
Nel caso in cui si volesse creare una associazione tra due tabelle, è possibile utilizzare le cosiddette foreign key: una foreign key è, in pratica, una colonna di una tabella (child) che fa riferimento ai valori univoci – la primary key – di un’altra tabella (parent). In questo modo, due o più tabelle possono essere collegate l’una all’altra (per esempio, non è possibile aggiungere nella tabella child una riga per cui il valore della foreign key non è presente nella tabelle parent).
Per recuperare informazioni da un RDBMS, è possibile inviare una query, cioè una richiesta strutturata di un set di informazioni. I database relazionali usano il linguaggio SQL (Structured Query Language) per definire e inviare tali richieste. Le query consentono di scegliere quali info estrarre e con quali clausole e criteri.
Configurazione e connessione
Nel momento in cui si crea una nuova applicazione Laravel, viene già creato il file di configurazione config/database.php che è pronto per far connettere l’applicazione ad uno qualsiasi dei database supportati.
Non è necessario, però, modificare tale file, a meno di non dover impostare qualche opzione aggiuntiva particolare. Laravel, infatti, permette di impostare i valori esatti della propria connessione a un database tramite il file .env presente nella directory root del progetto.
In tale file possiamo trovare la seguente configurazione:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=
La prima variabile ambientale, DB_CONNECTION, indica quale delle connessioni indicate nel file config/database.php verrà utilizzata. Sono pre-configurate diverse connessioni, una per tipo di database supportato (sqlite, mysql per MariaDB e MySQL, pgsql per PostgreSQL, sqlsrv per SQL Server), ognuna con già impostato il driver opportuno e le opzioni aggiuntive dedicate.
Le altre variabili vanno impostate a seconda del tipo di database che utilizzeremo e, ovviamente, con i valori che ci permettono di puntare al nostro database.
Esecuzione di query SQL
Una volta configurata la connessione a un database (e supponendo che sul database siano già state create le opportune tabelle), sarà possibile eseguire query SQL in ogni classe della nostra applicazione tramite i vari metodi offerti dalla facade DB.
use Illuminate\Support\Facades\DB; class PostController extends Controller { public function index() { $posts = DB::select('select title from posts where active = :active', ['active' => 1]); $count = DB::scalar('select count(1) from posts where active = :active', ['active' => 1]); return view('posts', ['posts' => $posts, 'count' => $count]); } } <div> Post count is {{ $count }} <ul> @foreach($posts as $post) <li>{{ $post->title }}</li> @endforeach </ul> </div>
use Illuminate\Support\Facades\DB;
class PostController extends Controller
{
public function index()
{
$posts = DB::select('select title from posts where active = :active', ['active' => 1]);
$count = DB::scalar('select count(1) from posts where active = :active', ['active' => 1]);
return view('posts', ['posts' => $posts, 'count' => $count]);
}
}
<div>
Post count is {{ $count }}
<ul>
@foreach($posts as $post)
<li>{{ $post->title }}</li>
@endforeach
</ul>
</div>
I vari metodi della facade DB accettano come primo argomento la query SQL da eseguire. È possibile indicare eventuali parametri variabili della query tramite named binding dei parametri: nella query d’esempio, il valore della colonna active su cui è eseguita la WHERE è passato collegando il “segnaposto” :active con l’array passato come secondo argomento del metodo.
Il metodo DB::select restituisce un array di risultati, ciascuno dei quali è un oggetto PHP stdClass. Il metodo DB::scalar, invece, restituisce un singolo valore scalare, utile per le query di “count”.
È possibile inserire e modificare record con i metodi DB::insert e DB::update.
DB::insert( 'insert into posts (title, content, active) values (?, ?, ?)', ['Another Post', 'Some cool content', 1] ); // ... // $affected è in numero di righe cambiate dalla query $affected = DB::update( 'update posts set active = 0 where title LIKE ?', ['%DRAFT%'] );
DB::insert(
'insert into posts (title, content, active) values (?, ?, ?)',
['Another Post', 'Some cool content', 1]
);
// ...
// $affected è in numero di righe cambiate dalla query
$affected = DB::update(
'update posts set active = 0 where title LIKE ?',
['%DRAFT%']
);
Notare il diverso tipo di binding dei parametri della query, realizzato con ?.
È, ovviamente, disponibile la possibilità di eseguire le varie query tramite transazione. Una transazione permette di eseguire diverse operazioni sul database, facendo rollback di tutte quelle eseguite fino a un certo punto se una delle varie operazioni non dovesse riuscire.
DB::transaction(function () { DB::update('update posts set active = 8'); DB::delete('delete from comments'); });
DB::transaction(function () {
DB::update('update posts set active = 8');
DB::delete('delete from comments');
});
Query Builder
Scrivere query SQL a mano e poi passare come array gli eventuali parametri variabili è poco pratico, specie quando il numero di colonne di una tabella su cui si vuole aggiungere condizioni non è piccolo.
La facade DB offre un metodo per costruire query utilizzando costrutti PHP.
$posts = DB::table('posts')->where('active', 1)->get('title'); $count = DB::table('posts')->where('active', 1)->count();
$posts = DB::table('posts')->where('active', 1)->get('title');
$count = DB::table('posts')->where('active', 1)->count();
Attenzione però: l’ordine con cui si “concatenano” i vari tipi di metodi è importante. Il metodo where, infatti, aggiunge una clausola WHERE al builder, mentre sono effettivamente i metodi get e count a dare il via all’esecuzione della query.
Rimandiamo alla documentazione ufficiale di Laravel per dettagli sulle varie possibilità offerte dal query builder.
Comando Artisan per database
Il comando Artisan db permette di collegarsi al database configurato nell’applicazione Laravel dalla riga di comando. Vari sottocomandi sono disponibili per ricavare informazioni sul database o sulle singole tabelle.
$ php artisan db:show SQLite .................................................. Database ....................... database/database.sqlite Host .................................................... Port .................................................... Username ................................................ URL ..................................................... Open Connections ........................................ Tables ................................................ 6 Table ........................................ Size (MiB) failed_jobs ........................................... — migrations ............................................ — password_resets ....................................... — personal_access_tokens ................................ — posts ................................................. — users ................................................. — $ php artisan db:table posts posts .................................................... Columns ................................................ 3 Column .............................................. Type id autoincrement, integer ........................ integer title text .......................................... text active integer ................................. 1 integer Index .................................................... primary id ............................... unique, primary
$ php artisan db:show
SQLite ..................................................
Database ....................... database/database.sqlite
Host ....................................................
Port ....................................................
Username ................................................
URL .....................................................
Open Connections ........................................
Tables ................................................ 6
Table ........................................ Size (MiB)
failed_jobs ........................................... —
migrations ............................................ —
password_resets ....................................... —
personal_access_tokens ................................ —
posts ................................................. —
users ................................................. —
$ php artisan db:table posts
posts ....................................................
Columns ................................................ 3
Column .............................................. Type
id autoincrement, integer ........................ integer
title text .......................................... text
active integer ................................. 1 integer
Index ....................................................
primary id ............................... unique, primary