Setup del database
Dopo la serie di articoli dedicati ad Eloquent è ora di mettere in pratica quanto appreso nel nostro progetto. La prima cosa da fare è quella di configurare i parametri di connessione al database.
Il file di configurazione dedicato al database è banalmente config/database.php
ma il miglior modo di configurare i parametri è utilizzare il file .env
in modo da poter riutilizzare gli stessi file su diversi ambienti; .env
contiene infatti tutte le configurazioni dipendenti dall'ambiente. Le property interessate sono:
Property | Descrizione |
---|---|
DB_CONNECTION | Contiene la tipologia di database utilizzato, di default MySQL |
DB_HOST | Contiene l'ip o l'indirizzo del server db |
DB_DATABASE | Contiene il nome del database |
DB_USERNAME | Contiene lo username |
DB_PASSWORD | Contiene la password |
Definizione dei modelli
I primi modelli che creeremo all'interno della nostra applicazione saranno Book
e Author
. La relazione che intercorrerà tra di essi sarà la classica uno-a-molti basandoci sulla convenzione che un libro abbia un solo autore e lo stesso autore può aver scritto più libri. Oltre a questa relazione esisterà anche una relazione molti-a-molti tra utente e libro che rappresenta la lettura di un libro: un utente può aver letto più libri e un libro può essere stato letto da più utenti. L'entità User
viene definita di default da Laravel e non ci sarà bisogno di crearla, sia a livello di classe PHP sia di migration.
Partiamo quindi con la creazione delle tabelle tramite le relative migrations. I comandi da eseguire sono:
php artisan make:migration create_books_table
php artisan make:migration create_authors_table
php artisan make:migration create_book_user_table
La prima tabella (books
) rappresenta l'entità Book
, la seconda tabella (authors
) rappresenta l'entità Author
e la terza tabella (bookuser
) rappresenta la relazione molti-a-molti tra User
e Book
.
Tutte le migrations dovranno implementare sia il metodo up
che il metodo down
. I metodi up
si occuperanno della definizione vera a propria della tabella, mentre i down
solo della loro eliminazione:
// metodo up di create_books_table
Schema::create('authors', function (Blueprint $table)
{
$table->increments('id');
$table->string('firstname');
$table->string('lastname');
$table->timestamps();
});
// metodo up di create_authors_table
Schema::create('books', function (Blueprint $table)
{
$table->increments('id');
$table->string('title');
$table->integer('author_id')->unsigned();
$table->timestamps();
});
Schema::table('books', function (Blueprint $table)
{
$table->foreign('author_id')
->references('id')->on('authors')
->onDelete('cascade');
});
// metodo up di create_book_user_table
Schema::create('book_user', function (Blueprint $table)
{
$table->integer('book_id')->unsigned();
$table->integer('user_id')->unsigned();
$table->timestamps();
});
Schema::table('book_user', function (Blueprint $table)
{
$table->foreign('book_id')
->references('id')->on('books')
->onDelete('cascade');
$table->foreign('user_id')
->references('id')->on('users')
->onDelete('cascade');
});
Nel primo file vengono create 3 colonne (id
, firstname
e lastname
) e le colonne createdat
e updatedat
grazie al metodo dedicato timestamps(). Nel secondo file vengono create 3 colonne (id
, title
e author_id
) e le colonne timestamps. Viene inoltre creato una chiave esterna verso la tabella authors
. Da notare che la chiave esterna viene creata tramite una seconda query, in modo da avere la struttura dati già definita. Nel terzo file, quello della tabella pivot, vengono create le due colonne contenenti le chiavi esterne e i metodi timestamps.
Una volta definite le migrations, lanciamo php artisan migrate
e, se tutto ok, dovremmo ritrovarci con le 3 tabelle create sul database (più l'eventuale tabella users
creata di default da Laravel). Passiamo ora alla definizione delle classi PHP che rappresentano i modelli. Da linea di comando lanciamo:
php artisan make:model Book
php artisan make:model Author
e andiamo a configure le relazioni utilizzando i metodi di Eloquent:
// User.php
public function books()
{
return $this->hasMany('Biblios\Book')->withTimestamps();
}
// Book.php
public function author()
{
return $this->belongsTo('Biblios\Author');
}
public function users()
{
return $this->hasMany('Biblios\User')->withTimestamps();
}
// Author.php
public function books()
{
return $this->hasMany('Biblios\Book');
}
La configurazione è abbastanza triviale, grazie al fatto che abbiamo utilizzato i nomi convenzionali per le tabelle e le colonne. L'unica funzionalità degna di nota è l'utilizzo di withTimestamps()
in coda a hasMany
in modo da avere accesso alle informazioni temporali all'interno della tabella pivot di relazione.
Il primo step è quindi completato. Prima di andare oltre possiamo testare quanto fatto utilizzando tinker, la console disponibile in Laravel. Lanciamo quindi php artisan tinker
e eseguiamo il comando:
use Biblios\Author;
use Biblios\Book;
$author = new Author();
$author->firstname = 'Nome autore';
$author->lastname = 'Cognome autore';
$author->save();
$book = new Book();
$book->title = 'Prova titolo';
$book->author()->associate($author);
$book->save();
Se tutto è stato implementato correttamente non dovremmo ottenere errori.
Factory e seed
Lo step successivo prevede di definire dei seed che si occuperanno di creare dei dati di test nel database. Le factory sono classi che si occupano di costruire istanze di particolari modelli inserendo dei dati di test nelle loro property. Creiamo quindi 2 file all'interno di database/factories
ciascuno dedicato ad un modello: AuthorFactory
e BookFactory
.
// author factory
$factory->define(Biblios\Author::class, function (Faker\Generator $faker)
{
return [
'firstname' => $faker->firstName,
'lastname' => $faker->lastName
];
});
// book factory
$factory->define(Biblios\Book::class, function (Faker\Generator $faker)
{
return [
'title' => $faker->sentence(rand(1,5))
];
});
Dopo le factory possiamo definire il nostro seeder con il comando: php artisan make:seed AuthorBookSeeder
. All'interno del file run del nostro nuovo file inseriamo quindi questa porzione di codice per creare 10 autori e 10 libri:
factory(Biblios\Author::class, 10)->create()->each(function($author)
{
foreach(range(1, 10) as $i)
{
$author->books()->save(factory(Biblios\Book::class)->make());
}
});
Il seed può essere avviato con php artisan db:seed
e se tutto è stato implementato correttamente dovremmo ritrovarci un database popolato.