Migrazioni

Introduzione

Le migrazioni sono come il controllo delle versioni per il tuo database, permettendo al tuo team di definire e condividere la definizione dello schema del database dell’applicazione. Se hai mai dovuto dire a un collega di aggiungere manualmente una colonna al proprio schema del database locale dopo aver integrato le tue modifiche dal controllo del codice sorgente, hai affrontato il problema che le migrazioni del database risolvono.

La facade Schema di Laravel fornisce supporto agnostico per creare e manipolare tabelle su tutti i sistemi di database supportati da Laravel. Solitamente, le migrazioni utilizzano questa facade per creare e modificare tabelle e colonne del database.

Generazione delle Migrazioni

Puoi usare il comando make:migration di Artisan per creare una migrazione del database. La nuova migrazione sarà inserita nella directory database/migrations. Ogni file di migrazione contiene un timestamp che permette a Laravel di determinare l’ordine delle migrazioni:

php artisan make:migration create_flights_table

Laravel utilizzerà il nome della migrazione per cercare di indovinare il nome della tabella e se la migrazione creerà una nuova tabella. Se Laravel riesce a determinare il nome della tabella dal nome della migrazione, il file di migrazione generato sarà precompilato con la tabella specificata. Altrimenti, potrai specificare manualmente la tabella nel file di migrazione.

Se desideri specificare un percorso personalizzato per la migrazione generata, puoi usare l’opzione --path quando esegui il comando make:migration. Il percorso fornito deve essere relativo al percorso base della tua applicazione.

I template delle migrazioni possono essere personalizzati usando la pubblicazione dei stub.

Comprimi le Migrazioni

Man mano che sviluppi la tua applicazione, potresti accumulare sempre più migrazioni nel tempo. Questo può portare a una directory database/migrations ingombrante con potenzialmente centinaia di migrazioni. Se lo desideri, puoi "comprimere" le tue migrazioni in un unico file SQL. Per iniziare, esegui il comando schema:dump:

php artisan schema:dump

# Effettua il dump dello schema del database attuale e rimuovi tutte le migrazioni esistenti...
php artisan schema:dump --prune

Quando esegui questo comando, Laravel scriverà un file "schema" nella directory database/schema della tua applicazione. Il nome del file dello schema corrisponderà alla connessione al database. Ora, quando tenti di migrare il tuo database e nessun’altra migrazione è stata eseguita, Laravel eseguirà prima le istruzioni SQL nel file dello schema della connessione al database che stai utilizzando. Dopo aver eseguito le istruzioni SQL del file dello schema, Laravel eseguirà tutte le migrazioni rimanenti che non facevano parte del dump dello schema.

Se i test della tua applicazione usano una connessione al database diversa da quella che usi normalmente durante lo sviluppo locale, dovresti assicurarti di aver effettuato il dump di un file di schema utilizzando quella connessione al database in modo che i tuoi test possano costruire il tuo database. Potresti voler fare questo dopo aver effettuato il dump della connessione al database che usi normalmente durante lo sviluppo locale:

php artisan schema:dump
php artisan schema:dump --database=testing --prune

Dovresti aggiungere il tuo file di schema del database al controllo del codice sorgente in modo che altri sviluppatori del tuo team possano rapidamente creare la struttura iniziale del database della tua applicazione.

La compressione delle migrazioni è disponibile solo per i database MariaDB, MySQL, PostgreSQL e SQLite e utilizza il client a riga di comando del database.

Struttura delle migration

Una classe di migration contiene due metodi: up e down. Il metodo up viene usato per aggiungere nuove tabelle, colonne o indici al tuo database, mentre il metodo down deve invertire le operazioni eseguite dal metodo up.

All’interno di entrambi i metodi, puoi usare il builder Schema di Laravel per creare e modificare tabelle in modo espressivo. Per conoscere tutti i metodi disponibili sul builder Schema, consulta la sua documentazione. Ad esempio, la seguente migration crea una tabella flights:

    <?php

    use Illuminate\Database\Migrations\Migration;
    use Illuminate\Database\Schema\Blueprint;
    use Illuminate\Support\Facades\Schema;

    return new class extends Migration
    {
        /**
         * Esegui le migrations.
         */
        public function up(): void
        {
            Schema::create('flights', function (Blueprint $table) {
                $table->id();
                $table->string('name');
                $table->string('airline');
                $table->timestamps();
            });
        }

        /**
         * Annulla le migrations.
         */
        public function down(): void
        {
            Schema::drop('flights');
        }
    };

Impostare la Connessione della Migrazione

Se la tua migrazione interagisce con una connessione al database diversa dalla connessione predefinita della tua applicazione, dovresti impostare la proprietà $connection della tua migrazione:

    /**
     * La connessione al database che deve essere usata dalla migrazione.
     *
     * @var string
     */
    protected $connection = 'pgsql';

    /**
     * Esegui le migrazioni.
     */
    public function up(): void
    {
        // ...
    }

Eseguire le Migrazioni

Per eseguire tutte le migrazioni in sospeso, esegui il comando Artisan migrate:

php artisan migrate

Se vuoi vedere quali migrazioni sono state eseguite finora, puoi usare il comando Artisan migrate:status:

php artisan migrate:status

Se vuoi vedere le istruzioni SQL che verranno eseguite dalle migrazioni senza eseguirle realmente, puoi usare l’opzione --pretend con il comando migrate:

php artisan migrate --pretend

Isolamento dell’Esecuzione delle Migration

Se stai distribuendo la tua applicazione su più server ed eseguendo migrations come parte del processo di deployment, probabilmente non vuoi che due server tentino di migrare il database allo stesso tempo. Per evitare ciò, puoi usare l’opzione isolated quando invochi il comando migrate.

Quando viene fornita l’opzione isolated, Laravel acquisirà un lock atomico utilizzando il driver di cache della tua applicazione prima di tentare di eseguire le migrations. Tutti gli altri tentativi di eseguire il comando migrate mentre quel lock è attivo non verranno eseguiti; tuttavia, il comando terminerà comunque con un codice di uscita di successo:

php artisan migrate --isolated

Per utilizzare questa funzionalità, la tua applicazione deve usare il driver di cache memcached, redis, dynamodb, database, file o array come driver di cache predefinito. Inoltre, tutti i server devono comunicare con lo stesso server di cache centrale.

Forzare l’esecuzione delle migrazioni in produzione

Alcune operazioni di migrazione possono essere distruttive, il che significa che potrebbero causare la perdita di dati. Per proteggerti dall’esecuzione di questi comandi sul database di produzione, verrà richiesta una conferma prima che i comandi vengano eseguiti. Per forzare l’esecuzione dei comandi senza richiesta, usa l’opzione --force:

php artisan migrate --force

Annullare le Migrazioni

Per annullare l’ultima operazione di migrazione, puoi usare il comando Artisan rollback. Questo comando annulla l’ultimo "batch" di migrazioni, che può includere più file di migrazione:

php artisan migrate:rollback

Puoi annullare un numero limitato di migrazioni fornendo l’opzione --step al comando rollback. Ad esempio, il seguente comando annullerà le ultime cinque migrazioni:

php artisan migrate:rollback --step=5

Puoi annullare uno specifico "batch" di migrazioni fornendo l’opzione --batch al comando rollback, dove l’opzione batch corrisponde a un valore di batch nella tabella migrations del tuo database. Ad esempio, il seguente comando annullerà tutte le migrazioni nel batch tre:

php artisan migrate:rollback --batch=3

Se vuoi vedere le istruzioni SQL che verranno eseguite dalle migrazioni senza eseguirle effettivamente, puoi aggiungere l’opzione --pretend al comando migrate:rollback:

php artisan migrate:rollback --pretend

Il comando migrate:reset annullerà tutte le migrazioni della tua applicazione:

php artisan migrate:reset

Ripristina e Esegui le Migrazioni con un Solo Comando

Il comando migrate:refresh annulla tutte le tue migrazioni e poi esegue il comando migrate. Questo comando ricrea effettivamente tutto il tuo database:

php artisan migrate:refresh
php artisan migrate:refresh --seed

Puoi annullare e riapplicare un numero limitato di migrazioni fornendo l’opzione step al comando refresh. Ad esempio, il comando seguente annullerà e riapplicherà le ultime cinque migrazioni:

php artisan migrate:refresh --step=5

Elimina tutte le tabelle e migra

Il comando migrate:fresh elimina tutte le tabelle dal database e poi esegue il comando migrate:

php artisan migrate:fresh
php artisan migrate:fresh --seed

Per impostazione predefinita, il comando migrate:fresh elimina solo le tabelle dalla connessione di database predefinita. Tuttavia, puoi usare l’opzione --database per specificare la connessione di database da migrare. Il nome della connessione di database deve corrispondere a una connessione definita nel file di configurazione database della tua applicazione:

php artisan migrate:fresh --database=admin

Il comando migrate:fresh eliminerà tutte le tabelle del database indipendentemente dal loro prefisso. Questo comando deve essere usato con cautela quando si sviluppa su un database condiviso con altre applicazioni.

Tabelle

Creazione delle Tabelle

Per creare una nuova tabella nel database, utilizza il metodo create sulla facade Schema. Il metodo create accetta due argomenti: il primo è il nome della tabella, mentre il secondo è una closure che riceve un oggetto Blueprint che può essere utilizzato per definire la nuova tabella:

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

Schema::create('users', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->string('email');
    $table->timestamps();
});

Quando crei la tabella, puoi utilizzare uno qualsiasi dei metodi delle colonne del costruttore dello schema per definire le colonne della tabella.

Determinare l’esistenza di Tabelle/Colonne

Puoi verificare l’esistenza di una tabella, una colonna o un indice utilizzando i metodi hasTable, hasColumn e hasIndex:

if (Schema::hasTable('users')) {
    // La tabella "users" esiste...
}

if (Schema::hasColumn('users', 'email')) {
    // La tabella "users" esiste e ha una colonna "email"...
}

if (Schema::hasIndex('users', ['email'], 'unique')) {
    // La tabella "users" esiste e ha un indice unico sulla colonna "email"...
}

Connessione al Database e Opzioni della Tabella

Se vuoi eseguire un’operazione sullo schema su una connessione al database che non è la connessione predefinita dell’applicazione, usa il metodo connection:

    Schema::connection('sqlite')->create('users', function (Blueprint $table) {
        $table->id();
    });

Inoltre, alcune altre proprietà e metodi possono essere utilizzati per definire aspetti aggiuntivi della creazione della tabella. La proprietà engine può essere usata per specificare il motore di archiviazione della tabella quando si utilizza MariaDB o MySQL:

    Schema::create('users', function (Blueprint $table) {
        $table->engine('InnoDB');

        // ...
    });

Le proprietà charset e collation possono essere usate per specificare il set di caratteri e la collation per la tabella creata quando si utilizza MariaDB o MySQL:

    Schema::create('users', function (Blueprint $table) {
        $table->charset('utf8mb4');
        $table->collation('utf8mb4_unicode_ci');

        // ...
    });

Il metodo temporary può essere usato per indicare che la tabella deve essere "temporanea". Le tabelle temporanee sono visibili solo alla sessione del database della connessione corrente e vengono eliminate automaticamente quando la connessione viene chiusa:

    Schema::create('calculations', function (Blueprint $table) {
        $table->temporary();

        // ...
    });

Se desideri aggiungere un "commento" a una tabella del database, puoi invocare il metodo comment sull’istanza della tabella. I commenti sulle tabelle sono attualmente supportati solo da MariaDB, MySQL e PostgreSQL:

    Schema::create('calculations', function (Blueprint $table) {
        $table->comment('Business calculations');

        // ...
    })

Aggiornare Tabelle

Il metodo table sulla facade Schema può essere utilizzato per aggiornare tabelle esistenti. Come il metodo create, il metodo table accetta due argomenti: il nome della tabella e una closure che riceve un’istanza di Blueprint che puoi usare per aggiungere colonne o indici alla tabella:

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

Schema::table('users', function (Blueprint $table) {
    $table->integer('votes');
});

Rinomina / Eliminazione Tabelle

Per rinominare una tabella del database esistente, utilizza il metodo rename:

    use Illuminate\Support\Facades\Schema;

    Schema::rename($from, $to);

Per eliminare una tabella esistente, puoi utilizzare i metodi drop o dropIfExists:

    Schema::drop('users');

    Schema::dropIfExists('users');

Rinominare Tabelle con Chiavi Esterne

Prima di rinominare una tabella, dovresti verificare che eventuali vincoli di chiave esterna sulla tabella abbiano un nome esplicito nei tuoi file di migrazione invece di lasciare che Laravel assegni un nome basato su convenzioni. Altrimenti, il nome del vincolo di chiave esterna farà riferimento al vecchio nome della tabella.

Colonne

Creazione delle Colonne

Il metodo table sul facade Schema può essere utilizzato per aggiornare tabelle esistenti. Come il metodo create, il metodo table accetta due argomenti: il nome della tabella e una closure che riceve un’istanza di Illuminate\Database\Schema\Blueprint che puoi usare per aggiungere colonne alla tabella:

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

Schema::table('users', function (Blueprint $table) {
    $table->integer('votes');
});

Tipi di Colonna Disponibili

Il blueprint del costruttore di schema offre una varietà di metodi che corrispondono ai diversi tipi di colonne che puoi aggiungere alle tue tabelle di database. Ciascuno dei metodi disponibili è elencato nella tabella sottostante:

bigIncrements()

Il metodo bigIncrements crea una colonna auto-incrementante di tipo UNSIGNED BIGINT (chiave primaria):

$table->bigIncrements('id');

bigInteger()

Il metodo bigInteger crea una colonna equivalente a BIGINT:

$table->bigInteger('votes');

binary()

Il metodo binary crea una colonna equivalente a BLOB:

$table->binary('photo');

Quando si utilizza MySQL, MariaDB o SQL Server, è possibile passare gli argomenti length e fixed per creare una colonna equivalente a VARBINARY o BINARY:

$table->binary('data', length: 16); // VARBINARY(16)

$table->binary('data', length: 16, fixed: true); // BINARY(16)

boolean()

Il metodo boolean crea una colonna equivalente a BOOLEAN:

$table->boolean('confirmed');

char()

Il metodo char crea una colonna equivalente a CHAR con una lunghezza specificata:

$table->char('name', length: 100);

dateTimeTz()

Il metodo dateTimeTz crea una colonna equivalente di tipo DATETIME (con fuso orario) con una precisione opzionale per i secondi frazionari:

$table->dateTimeTz('created_at', precision: 0);

dateTime()

Il metodo dateTime crea una colonna equivalente a DATETIME con una precisione opzionale per i secondi frazionari:

$table->dateTime('created_at', precision: 0);

date()

Il metodo date crea una colonna di tipo DATE:

$table->date('created_at');

decimal()

Il metodo decimal crea una colonna equivalente a DECIMAL con la precisione specificata (numero totale di cifre) e la scala (cifre decimali):

    $table->decimal('amount', total: 8, places: 2);

double()

Il metodo double crea una colonna equivalente a DOUBLE:

$table->double('amount');

enum()

Il metodo enum crea una colonna equivalente a ENUM con i valori validi forniti:

$table->enum('difficulty', ['easy', 'hard']);

float()

Il metodo float crea una colonna di tipo FLOAT con la precisione fornita:

$table->float('amount', precision: 53);

foreignId()

Il metodo foreignId crea una colonna equivalente a UNSIGNED BIGINT:

    $table->foreignId('user_id');

foreignIdFor()

Il metodo foreignIdFor aggiunge una colonna equivalente a {column}_id per una determinata classe di modello. Il tipo di colonna sarà UNSIGNED BIGINT, CHAR(36) o CHAR(26) a seconda del tipo di chiave del modello:

    $table->foreignIdFor(User::class);

foreignUlid()

Il metodo foreignUlid crea una colonna equivalente a ULID:

$table->foreignUlid('user_id');

foreignUuid()

Il metodo foreignUuid crea una colonna equivalente a UUID:

$table->foreignUuid('user_id');

geography()

Il metodo geography crea una colonna equivalente a GEOGRAPHY con il tipo spaziale specificato e lo SRID (Spatial Reference System Identifier):

$table->geography('coordinates', subtype: 'point', srid: 4326);

Il supporto per i tipi spaziali dipende dal driver del tuo database. Consulta la documentazione del tuo database. Se la tua applicazione utilizza un database PostgreSQL, devi installare l’estensione PostGIS prima di poter utilizzare il metodo geography.

geometry()

Il metodo geometry crea una colonna equivalente a GEOMETRY con il tipo spaziale specificato e SRID (Spatial Reference System Identifier):

$table->geometry('positions', subtype: 'point', srid: 0);

Il supporto per i tipi spaziali dipende dal driver del tuo database. Consulta la documentazione del tuo database. Se la tua applicazione utilizza un database PostgreSQL, devi installare l’estensione PostGIS prima di poter utilizzare il metodo geometry.

id()

Il metodo id è un alias del metodo bigIncrements. Di default, il metodo creerà una colonna id; tuttavia, puoi passare un nome di colonna se vuoi assegnare un nome diverso alla colonna:

$table->id();

increments()

Il metodo increments crea una colonna UNSIGNED INTEGER auto-incrementante equivalente come chiave primaria:

$table->increments('id');

integer()

Il metodo integer crea una colonna equivalente a INTEGER:

$table->integer('votes');

ipAddress()

Il metodo ipAddress crea una colonna equivalente a VARCHAR:

    $table->ipAddress('visitor');

Quando si usa PostgreSQL, verrà creata una colonna INET.

json()

Il metodo json crea una colonna equivalente JSON:

$table->json('options');

jsonb()

Il metodo jsonb crea una colonna equivalente a JSONB:

$table->jsonb('options');

longText()

Il metodo longText crea una colonna equivalente a LONGTEXT:

$table->longText('description');

Quando si utilizza MySQL o MariaDB, puoi applicare un set di caratteri binary alla colonna per creare una colonna equivalente a LONGBLOB:

$table->longText('data')->charset('binary'); // LONGBLOB

macAddress()

Il metodo macAddress crea una colonna destinata a contenere un indirizzo MAC. Alcuni sistemi di database, come PostgreSQL, hanno un tipo di colonna dedicato per questo tipo di dati. Altri sistemi di database utilizzeranno una colonna equivalente come stringa:

$table->macAddress('device');

mediumIncrements()

Il metodo mediumIncrements crea una colonna auto-incrementante equivalente a UNSIGNED MEDIUMINT come chiave primaria:

$table->mediumIncrements('id');

mediumInteger()

Il metodo mediumInteger crea una colonna equivalente a MEDIUMINT:

$table->mediumInteger('votes');

mediumText()

Il metodo mediumText crea una colonna equivalente a MEDIUMTEXT:

$table->mediumText('description');

Quando utilizzi MySQL o MariaDB, puoi applicare un set di caratteri binary alla colonna per creare una colonna equivalente a MEDIUMBLOB:

$table->mediumText('data')->charset('binary'); // MEDIUMBLOB

morphs()

Il metodo morphs è un metodo di comodo che aggiunge una colonna equivalente a {column}_id e una colonna VARCHAR equivalente a {column}_type. Il tipo di colonna per {column}_id sarà UNSIGNED BIGINT, CHAR(36) o CHAR(26) a seconda del tipo di chiave del modello.

Questo metodo è pensato per essere usato quando si definiscono le colonne necessarie per una relazione polimorfica Eloquent. Nell’esempio seguente, verranno create le colonne taggable_id e taggable_type:

    $table->morphs('taggable');

nullableTimestamps()

Il metodo nullableTimestamps è un alias del metodo timestamps:

$table->nullableTimestamps(precision: 0);

nullableMorphs()

Il metodo è simile al metodo morphs; tuttavia, le colonne create saranno "nullable":

    $table->nullableMorphs('taggable');

nullableUlidMorphs()

Il metodo è simile al metodo ulidMorphs; tuttavia, le colonne create saranno "nullable":

$table->nullableUlidMorphs('taggable');

nullableUuidMorphs()

Questo metodo è simile al metodo uuidMorphs; tuttavia, le colonne create saranno "nullable":

$table->nullableUuidMorphs('taggable');

rememberToken()

Il metodo rememberToken crea una colonna che può essere nulla, equivalente a VARCHAR(100), destinata a memorizzare il token di autenticazione "ricordami" authentication token:

    $table->rememberToken();

set()

Il metodo set crea una colonna equivalente a SET con la lista di valori validi forniti:

$table->set('flavors', ['strawberry', 'vanilla']);

smallIncrements()

Il metodo smallIncrements crea una colonna primaria auto-incrementante di tipo UNSIGNED SMALLINT:

$table->smallIncrements('id');

smallInteger()

Il metodo smallInteger crea una colonna equivalente a SMALLINT:

    $table->smallInteger('votes');

softDeletesTz()

Il metodo softDeletesTz aggiunge una colonna deleted_at di tipo TIMESTAMP (con fuso orario) che può essere nulla e con una precisione opzionale dei secondi frazionari. Questa colonna serve a memorizzare il timestamp deleted_at necessario per la funzionalità di "soft delete" di Eloquent:

    $table->softDeletesTz('deleted_at', precision: 0);

softDeletes()

Il metodo softDeletes aggiunge una colonna deleted_at di tipo TIMESTAMP che può essere nulla, con una precisione opzionale per i secondi frazionari. Questa colonna serve a memorizzare il timestamp deleted_at necessario per la funzionalità di "soft delete" di Eloquent:

$table->softDeletes('deleted_at', precision: 0);

string()

Il metodo string crea una colonna equivalente a VARCHAR della lunghezza specificata:

$table->string('name', length: 100);

text()

Il metodo text crea una colonna equivalente a TEXT:

    $table->text('description');

Quando usi MySQL o MariaDB, puoi applicare un set di caratteri binary alla colonna per creare una colonna equivalente a BLOB:

    $table->text('data')->charset('binary'); // BLOB

timeTz()

Il metodo timeTz crea una colonna TIME (con fuso orario) equivalente, con una precisione opzionale per le frazioni di secondi:

$table->timeTz('sunrise', precision: 0);

time()

Il metodo time crea una colonna equivalente a TIME con una precisione opzionale per i secondi frazionari:

$table->time('sunrise', precision: 0);

timestampTz()

Il metodo timestampTz crea una colonna equivalente a TIMESTAMP (con fuso orario) con una precisione opzionale dei secondi frazionari:

    $table->timestampTz('added_at', precision: 0);

timestamp()

Il metodo timestamp crea una colonna equivalente a TIMESTAMP con una precisione opzionale per i secondi frazionari:

$table->timestamp('added_at', precision: 0);

timestampsTz()

Il metodo timestampsTz crea le colonne created_at e updated_at come TIMESTAMP (con fuso orario) con una precisione opzionale per i secondi frazionati:

    $table->timestampsTz(precision: 0);

timestamps()

Il metodo timestamps crea le colonne created_at e updated_at equivalenti a TIMESTAMP con una precisione facoltativa per i secondi frazionari:

    $table->timestamps(precision: 0);

tinyIncrements()

Il metodo tinyIncrements crea una colonna UNSIGNED TINYINT auto-incrementante come chiave primaria:

    $table->tinyIncrements('id');

tinyInteger()

Il metodo tinyInteger crea una colonna equivalente a TINYINT:

$table->tinyInteger('votes');

tinyText()

Il metodo tinyText crea una colonna equivalente a TINYTEXT:

$table->tinyText('notes');

Quando si utilizza MySQL o MariaDB, puoi applicare un set di caratteri binary alla colonna per creare una colonna equivalente a TINYBLOB:

$table->tinyText('data')->charset('binary'); // TINYBLOB

unsignedBigInteger()

Il metodo unsignedBigInteger crea una colonna equivalente a UNSIGNED BIGINT:

$table->unsignedBigInteger('votes');

unsignedInteger()

Il metodo unsignedInteger crea una colonna equivalente a UNSIGNED INTEGER:

    $table->unsignedInteger('votes');

unsignedMediumInteger()

Il metodo unsignedMediumInteger crea una colonna equivalente a UNSIGNED MEDIUMINT:

$table->unsignedMediumInteger('votes');

unsignedSmallInteger()

Il metodo unsignedSmallInteger crea una colonna equivalente a UNSIGNED SMALLINT:

$table->unsignedSmallInteger('votes');

unsignedTinyInteger()

Il metodo unsignedTinyInteger crea una colonna equivalente a UNSIGNED TINYINT:

$table->unsignedTinyInteger('votes');

ulidMorphs()

Il metodo ulidMorphs è un metodo di comodità che aggiunge una colonna {column}_id equivalente a CHAR(26) e una colonna {column}_type equivalente a VARCHAR.

Questo metodo è pensato per essere utilizzato quando si definiscono le colonne necessarie per una relazione polimorfica Eloquent che utilizza identificatori ULID. Nel seguente esempio, verranno create le colonne taggable_id e taggable_type:

    $table->ulidMorphs('taggable');

uuidMorphs()

Il metodo uuidMorphs è un metodo comodo che aggiunge una colonna {column}_id equivalente a CHAR(36) e una colonna {column}_type equivalente a VARCHAR.

Questo metodo è pensato per essere usato quando si definiscono le colonne necessarie per una relazione polimorfica Eloquent che utilizza identificatori UUID. Nell’esempio seguente, verranno create le colonne taggable_id e taggable_type:

    $table->uuidMorphs('taggable');

ulid()

Il metodo ulid crea una colonna equivalente a ULID:

$table->ulid('id');

uuid()

Il metodo uuid crea una colonna equivalente a UUID:

$table->uuid('id');

vector()

Il metodo vector crea una colonna equivalente a vector:

$table->vector('embedding', dimensions: 100);

year()

Il metodo year crea una colonna di tipo YEAR:

$table->year('birth_year');

Modificatori di Colonna

Oltre ai tipi di colonna elencati sopra, ci sono diversi "modificatori" che puoi usare quando aggiungi una colonna a una tabella del database. Ad esempio, per rendere la colonna "nullable", puoi usare il metodo nullable:

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

Schema::table('users', function (Blueprint $table) {
    $table->string('email')->nullable();
});

La tabella seguente contiene tutti i modificatori di colonna disponibili. Questa lista non include i modificatori di indice:

Modificatore Descrizione
->after('column') Posiziona la colonna "dopo" un’altra colonna (MariaDB / MySQL).
->autoIncrement() Imposta le colonne INTEGER come auto-incrementanti (chiave primaria).
->charset('utf8mb4') Specifica un set di caratteri per la colonna (MariaDB / MySQL).
->collation('utf8mb4_unicode_ci') Specifica una collation per la colonna.
->comment('my comment') Aggiungi un commento a una colonna (MariaDB / MySQL / PostgreSQL).
->default($value) Specifica un valore "di default" per la colonna.
->first() Posiziona la colonna "prima" nella tabella (MariaDB / MySQL).
->from($integer) Imposta il valore iniziale di un campo auto-incrementante (MariaDB / MySQL / PostgreSQL).
->invisible() Rendi la colonna "invisibile" alle query SELECT * (MariaDB / MySQL).
->nullable($value = true) Permetti l’inserimento di valori NULL nella colonna.
->storedAs($expression) Crea una colonna generata memorizzata (MariaDB / MySQL / PostgreSQL / SQLite).
->unsigned() Imposta le colonne INTEGER come UNSIGNED (MariaDB / MySQL).
->useCurrent() Imposta le colonne TIMESTAMP per usare CURRENT_TIMESTAMP come valore di default.
->useCurrentOnUpdate() Imposta le colonne TIMESTAMP per usare CURRENT_TIMESTAMP quando un record viene aggiornato (MariaDB / MySQL).
->virtualAs($expression) Crea una colonna generata virtuale (MariaDB / MySQL / SQLite).
->generatedAs($expression) Crea una colonna di identità con opzioni di sequenza specificate (PostgreSQL).
->always() Definisce la precedenza dei valori di sequenza sugli input per una colonna di identità (PostgreSQL).

Espressioni di default

Il modificatore default accetta un valore o un’istanza di Illuminate\Database\Query\Expression. Utilizzare un’istanza di Expression impedirà a Laravel di racchiudere il valore tra virgolette e permetterà di usare funzioni specifiche del database. Una situazione in cui questo è particolarmente utile è quando devi assegnare valori predefiniti alle colonne JSON:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Query\Expression;
use Illuminate\Database\Migrations\Migration;

return new class extends Migration
{
    /**
     * Esegue le migrazioni.
     */
    public function up(): void
    {
        Schema::create('flights', function (Blueprint $table) {
            $table->id();
            $table->json('movies')->default(new Expression('(JSON_ARRAY())'));
            $table->timestamps();
        });
    }
};

Il supporto per le espressioni di default dipende dal driver del database, dalla versione del database e dal tipo di campo. Consulta la documentazione del tuo database.

Ordine delle colonne

Quando si utilizza il database MariaDB o MySQL, il metodo after può essere usato per aggiungere colonne dopo una colonna esistente nello schema:

$table->after('password', function (Blueprint $table) {
    $table->string('address_line1');
    $table->string('address_line2');
    $table->string('city');
});

Modificare Colonne

Il metodo change ti permette di modificare il tipo e gli attributi delle colonne esistenti. Ad esempio, potresti voler aumentare la dimensione di una colonna string. Per vedere il metodo change in azione, aumentiamo la dimensione della colonna name da 25 a 50. Per fare ciò, definiamo semplicemente il nuovo stato della colonna e poi chiamiamo il metodo change:

    Schema::table('users', function (Blueprint $table) {
        $table->string('name', 50)->change();
    });

Quando modifichi una colonna, devi includere esplicitamente tutti i modificatori che desideri mantenere nella definizione della colonna – qualsiasi attributo mancante verrà rimosso. Ad esempio, per mantenere gli attributi unsigned, default e comment, devi chiamare ogni modificatore esplicitamente quando cambi la colonna:

    Schema::table('users', function (Blueprint $table) {
        $table->integer('votes')->unsigned()->default(1)->comment('my comment')->change();
    });

Il metodo change non modifica gli indici della colonna. Pertanto, puoi usare i modificatori di indice per aggiungere o rimuovere esplicitamente un indice quando modifichi la colonna:

// Aggiungi un indice...
$table->bigIncrements('id')->primary()->change();

// Rimuovi un indice...
$table->char('postal_code', 10)->unique(false)->change();

Ridenominare le Colonne

Per rinominare una colonna, puoi usare il metodo renameColumn fornito dallo schema builder:

Schema::table('users', function (Blueprint $table) {
    $table->renameColumn('from', 'to');
});

Eliminare Colonne

Per eliminare una colonna, puoi usare il metodo dropColumn sullo schema builder:

Schema::table('users', function (Blueprint $table) {
    $table->dropColumn('votes');
});

Puoi eliminare più colonne da una tabella passando un array di nomi di colonne al metodo dropColumn:

Schema::table('users', function (Blueprint $table) {
    $table->dropColumn(['votes', 'avatar', 'location']);
});

Alias dei Comandi Disponibili

Laravel fornisce diversi metodi utili per eliminare tipi comuni di colonne. Ognuno di questi metodi è descritto nella tabella qui sotto:

Command Description
$table->dropMorphs('morphable'); Elimina le colonne morphable_id e morphable_type.
$table->dropRememberToken(); Elimina la colonna remember_token.
$table->dropSoftDeletes(); Elimina la colonna deleted_at.
$table->dropSoftDeletesTz(); Alias del metodo dropSoftDeletes().
$table->dropTimestamps(); Elimina le colonne created_at e updated_at.
$table->dropTimestampsTz(); Alias del metodo dropTimestamps().

Indici

Creare Indici

Il costruttore di schemi di Laravel supporta diversi tipi di indici. L’esempio seguente crea una nuova colonna email e specifica che i suoi valori devono essere unici. Per creare l’indice, possiamo concatenare il metodo unique alla definizione della colonna:

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

Schema::table('users', function (Blueprint $table) {
    $table->string('email')->unique();
});

In alternativa, puoi creare l’indice dopo aver definito la colonna. Per farlo, devi chiamare il metodo unique sul blueprint del costruttore di schemi. Questo metodo accetta il nome della colonna che deve ricevere un indice unico:

$table->unique('email');

Puoi anche passare un array di colonne a un metodo di indice per creare un indice composto:

$table->index(['account_id', 'created_at']);

Quando crei un indice, Laravel genererà automaticamente un nome per l’indice basato sulla tabella, sui nomi delle colonne e sul tipo di indice. Tuttavia, puoi passare un secondo argomento al metodo per specificare tu stesso il nome dell’indice:

$table->unique('email', 'unique_email');

Tipi di Indici Disponibili

La classe blueprint del builder dello schema di Laravel offre metodi per creare ogni tipo di indice supportato da Laravel. Ogni metodo per l’indice accetta un secondo argomento opzionale per specificare il nome dell’indice. Se omesso, il nome sarà derivato dai nomi della tabella e della(colonne) usate per l’indice, oltre al tipo di indice. Ognuno dei metodi di indice disponibili è descritto nella tabella sottostante:

Comando Descrizione
$table->primary('id'); Aggiunge una chiave primaria.
$table->primary(['id', 'parent_id']); Aggiunge chiavi composite.
$table->unique('email'); Aggiunge un indice unico.
$table->index('state'); Aggiunge un indice.
$table->fullText('body'); Aggiunge un indice full text (MariaDB / MySQL / PostgreSQL).
$table->fullText('body')->language('english'); Aggiunge un indice full text della lingua specificata (PostgreSQL).
$table->spatialIndex('location'); Aggiunge un indice spaziale (eccetto SQLite).

Ridenominare gli Indici

Per rinominare un indice, puoi usare il metodo renameIndex fornito dal blueprint dello schema builder. Questo metodo accetta il nome attuale dell’indice come primo argomento e il nome desiderato come secondo argomento:

$table->renameIndex('from', 'to')

Eliminare gli Indici

Per eliminare un indice, devi specificare il nome dell’indice. Per default, Laravel assegna automaticamente un nome all’indice basato sul nome della tabella, il nome della colonna indicizzata e il tipo di indice. Ecco alcuni esempi:

Comando Descrizione
$table->dropPrimary('users_id_primary'); Elimina una chiave primaria dalla tabella "users".
$table->dropUnique('users_email_unique'); Elimina un indice unico dalla tabella "users".
$table->dropIndex('geo_state_index'); Elimina un indice di base dalla tabella "geo".
$table->dropFullText('posts_body_fulltext'); Elimina un indice full text dalla tabella "posts".
$table->dropSpatialIndex('geo_location_spatialindex'); Elimina un indice spaziale dalla tabella "geo" (tranne SQLite).

Se passi un array di colonne in un metodo che elimina gli indici, il nome convenzionale dell’indice verrà generato in base al nome della tabella, alle colonne e al tipo di indice:

    Schema::table('geo', function (Blueprint $table) {
        $table->dropIndex(['state']); // Elimina l'indice 'geo_state_index'
    });

Vincoli di Chiave Esterna

Laravel offre il supporto per creare vincoli di chiave esterna, utilizzati per garantire l’integrità referenziale a livello di database. Ad esempio, definiamo una colonna user_id nella tabella posts che fa riferimento alla colonna id nella tabella users:

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

Schema::table('posts', function (Blueprint $table) {
    $table->unsignedBigInteger('user_id');

    $table->foreign('user_id')->references('id')->on('users');
});

Poiché questa sintassi è piuttosto prolissa, Laravel fornisce metodi aggiuntivi e più concisi che utilizzano le convenzioni per offrire una migliore esperienza di sviluppo. Utilizzando il metodo foreignId per creare la tua colonna, l’esempio sopra può essere riscritto in questo modo:

Schema::table('posts', function (Blueprint $table) {
    $table->foreignId('user_id')->constrained();
});

Il metodo foreignId crea una colonna equivalente a UNSIGNED BIGINT, mentre il metodo constrained utilizza le convenzioni per determinare la tabella e la colonna di riferimento. Se il nome della tua tabella non corrisponde alle convenzioni di Laravel, puoi fornirlo manualmente al metodo constrained. Inoltre, puoi specificare anche il nome che deve essere assegnato all’indice generato:

Schema::table('posts', function (Blueprint $table) {
    $table->foreignId('user_id')->constrained(
        table: 'users', indexName: 'posts_user_id'
    );
});

Puoi anche specificare l’azione desiderata per le proprietà "on delete" e "on update" del vincolo:

$table->foreignId('user_id')
      ->constrained()
      ->onUpdate('cascade')
      ->onDelete('cascade');

È disponibile anche una sintassi alternativa ed esplicativa per queste azioni:

Metodo Descrizione
$table->cascadeOnUpdate(); Gli aggiornamenti devono propagarsi.
$table->restrictOnUpdate(); Gli aggiornamenti devono essere limitati.
$table->nullOnUpdate(); Gli aggiornamenti impostano il valore della chiave esterna su null.
$table->noActionOnUpdate(); Nessuna azione sugli aggiornamenti.
$table->cascadeOnDelete(); Le cancellazioni devono propagarsi.
$table->restrictOnDelete(); Le cancellazioni devono essere limitate.
$table->nullOnDelete(); Le cancellazioni impostano il valore della chiave esterna su null.
$table->noActionOnDelete(); Previene le cancellazioni se esistono record figli.

Qualsiasi modificatore di colonna aggiuntivo deve essere chiamato prima del metodo constrained:

$table->foreignId('user_id')
      ->nullable()
      ->constrained();

Rimozione delle Foreign Keys

Per rimuovere una foreign key, puoi usare il metodo dropForeign, passando il nome del vincolo della foreign key da eliminare come argomento. I vincoli delle foreign key seguono la stessa convenzione di denominazione degli indici. In altre parole, il nome del vincolo della foreign key si basa sul nome della tabella e delle colonne nel vincolo, seguito dal suffisso "_foreign":

$table->dropForeign('posts_user_id_foreign');

In alternativa, puoi passare un array contenente il nome della colonna che contiene la foreign key al metodo dropForeign. L’array verrà convertito in un nome di vincolo della foreign key utilizzando le convenzioni di denominazione di Laravel:

$table->dropForeign(['user_id']);

Attivare e Disattivare i Vincoli di Chiave Esterna

Puoi abilitare o disabilitare i vincoli di chiave esterna nelle tue migrazioni utilizzando i seguenti metodi:

    Schema::enableForeignKeyConstraints();

    Schema::disableForeignKeyConstraints();

    Schema::withoutForeignKeyConstraints(function () {
        // Constraints disabled within this closure...
    });

SQLite disabilita i vincoli di chiave esterna per impostazione predefinita. Quando usi SQLite, assicurati di abilitare il supporto alle chiavi esterne nella configurazione del tuo database prima di tentare di crearle nelle tue migrazioni.

Eventi

Per comodità, ogni operazione di migrazione emetterà un event. Tutti gli eventi seguenti estendono la classe base Illuminate\Database\Events\MigrationEvent:

Classe Descrizione
Illuminate\Database\Events\MigrationsStarted Un gruppo di migrazioni sta per essere eseguito.
Illuminate\Database\Events\MigrationsEnded Un gruppo di migrazioni ha terminato l’esecuzione.
Illuminate\Database\Events\MigrationStarted Una singola migrazione sta per essere eseguita.
Illuminate\Database\Events\MigrationEnded Una singola migrazione ha terminato l’esecuzione.
Illuminate\Database\Events\NoPendingMigrations Un comando di migrazione non ha trovato migrazioni in sospeso.
Illuminate\Database\Events\SchemaDumped Un dump dello schema del database è stato completato.
Illuminate\Database\Events\SchemaLoaded Uno schema dump del database esistente è stato caricato.
Lascia un commento

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *