> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Pubblicazione e aggiornamento delle migrazioni di un pacchetto

> Partendo dall'implementazione di Laravel 13, spiega la differenza tra publishesMigrations e loadMigrationsFrom, la modifica dei timestamp durante la pubblicazione, i rischi della ripubblicazione e come distribuire le modifiche allo schema agli utenti esistenti.

Per mantenere nel tempo un pacchetto che usa il database non basta gestire la prima installazione: serve anche una procedura per distribuire le modifiche agli utenti che hanno già le tabelle. Progetta la pubblicazione, l'esecuzione e lo storico di esecuzione delle migrazioni come processi distinti.

Questa pagina presuppone le [basi dello sviluppo di pacchetti](/it/advanced/package-development) e analizza `ServiceProvider`, `VendorPublishCommand` e `Migrator` di Laravel 13. Il riferimento per l'implementazione del framework è `v13.34.0`.

## Copiare i file o caricarli dal pacchetto

| Metodo | Operazione del provider | Azione dell'utente | Dove risiedono i file |
| - | - | - | - |
| Pubblicare | `publishesMigrations()` | `migrate` dopo `vendor:publish` | `database/migrations` dell'applicazione |
| Caricare direttamente | `loadMigrationsFrom()` | `migrate` | All'interno del pacchetto installato |

`publishesMigrations()` si limita a registrare l'origine e la destinazione della copia come risorse pubblicabili. L'avvio del provider non copia alcun file né esegue SQL.

`loadMigrationsFrom()`, invece, registra un percorso di ricerca nel Migrator. Con il normale `migrate` vengono considerati anche i file di quel percorso, ma l'avvio del provider da solo non li esegue.

```mermaid theme={null}
flowchart TD
    A["Service provider del pacchetto"] --> B["publishesMigrations()<br>Registra origine e destinazione"]
    B --> C["vendor:publish<br>Copia nell'applicazione"]
    C --> E["migrate<br>Esegue i file non ancora eseguiti"]
    A --> D["loadMigrationsFrom()<br>Aggiunge al percorso di ricerca del Migrator"]
    D --> E
    E --> F["Registra i nomi dei file eseguiti<br>nella tabella migrations"]
```

Se l'utente deve poter adattare nomi di tabelle o colonne prima dell'esecuzione, la pubblicazione è l'opzione da considerare. Se è il pacchetto a gestire lo schema e non si prevede che l'utente modifichi i file, puoi valutare il caricamento diretto. I due esempi di provider che seguono sono alternativi.

<Warning>
  Evita di pubblicare una migrazione e, allo stesso tempo, di caricarla direttamente. Se il timestamp cambia durante la pubblicazione, origine e destinazione vengono trattate come voci distinte dello storico di esecuzione, e la stessa creazione di tabella potrebbe essere eseguita due volte.
</Warning>

## Implementare la pubblicazione

Assegna un tag specifico del pacchetto, così l'utente può pubblicare queste risorse separatamente dalle altre.

```php theme={null}
<?php

namespace Acme\Courier;

use Illuminate\Support\ServiceProvider;

class CourierServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        $this->publishesMigrations([
            __DIR__.'/../database/migrations' => database_path('migrations'),
        ], 'courier-migrations');
    }
}
```

Alla prima installazione, copia i file specificando provider e tag, controllane il contenuto e poi eseguili. Se indichi entrambi, Laravel seleziona le risorse pubblicabili con quel tag che appartengono a quel provider.

```bash theme={null}
php artisan vendor:publish --provider="Acme\Courier\CourierServiceProvider" --tag=courier-migrations
php artisan migrate:status
php artisan migrate
```

### La modifica del timestamp dipende dalla configurazione

La documentazione ufficiale descrive l'aggiornamento del timestamp delle migrazioni alla data e ora correnti durante la pubblicazione. Tuttavia, nell'implementazione di `ServiceProvider::publishesMigrations()`, l'origine viene aggiunta ai file soggetti all'aggiornamento del timestamp solo se `database.migrations.update_date_on_publish` è attivo. Il valore di fallback usato per leggere questa impostazione è `false`.

Il file `config/database.php` dell'applicazione standard di Laravel 13 contiene la configurazione seguente. Nelle applicazioni che hanno ereditato una struttura precedente, verifica anche che l'impostazione esista.

```php theme={null}
'migrations' => [
    'table' => 'migrations',
    'update_date_on_publish' => true,
],
```

Inoltre, `VendorPublishCommand` riscrive la data quando il file corrisponde al percorso reale di un'origine registrata e il nome di destinazione contiene il formato `YYYY_MM_DD_HHMMSS_`. Partendo dall'ora di avvio del comando, aggiunge un secondo per ogni file interessato. Se il nome non contiene questo formato, in quel passaggio la data non viene aggiunta.

```text theme={null}
Origine:
2026_09_01_000000_create_courier_deliveries_table.php

Esempio dopo la pubblicazione:
2026_10_02_120001_create_courier_deliveries_table.php
```

La data dopo la pubblicazione mostrata sopra è solo illustrativa. Il nome effettivo del file dipende dal momento della pubblicazione.

<Info>
  L'aggiornamento del timestamp dipende sia dalla registrazione nel pacchetto sia dalla configurazione dell'applicazione che lo usa. Non modificare questa impostazione in modo forzato dal provider del pacchetto: documenta invece il prerequisito nelle istruzioni di installazione. Se usi la cache della configurazione, dopo la modifica devi anche ricostruirla.
</Info>

## Ripubblicare non significa "aggiungere solo ciò che non è stato eseguito"

`vendor:publish` non controlla lo storico di esecuzione nel database. Inoltre, nella logica di copia di `v13.34.0`, l'esistenza del file viene verificata sulla destinazione **prima della modifica del timestamp**. Anche nella pubblicazione di una directory, si controlla prima se nella destinazione esiste lo stesso percorso relativo dell'origine, e solo dopo viene riscritta la data.

Di conseguenza, se alla prima pubblicazione la data è cambiata e nell'applicazione non esiste un file con lo stesso nome dell'origine, pubblicando di nuovo lo stesso tag potrebbe essere aggiunto un file con una data diversa. Non dare per scontato che, senza `--force`, i duplicati vengano sempre evitati.

| Condizione | Attenzione durante la ripubblicazione |
| - | - |
| Aggiornamento della data attivo e destinazione pre-modifica inesistente | Può essere aggiunta una copia con una data diversa |
| Aggiornamento della data disattivo e destinazione con lo stesso nome | Di norma il file esistente viene saltato |
| Con `--force` | Se le condizioni di copia sono soddisfatte e l'aggiornamento della data è attivo, il file può avere un nome diverso |
| Con `--existing` | Poiché si verifica l'esistenza della destinazione pre-modifica, la presenza del solo file con data modificata non garantisce che venga considerato |

### Lo stato di esecuzione si determina dal nome del file

`Migrator::getMigrationName()` restituisce il nome base del file senza `.php`. Per stabilire se una migrazione non è ancora stata eseguita, questo nome viene confrontato con lo storico di esecuzione. La verifica non si basa sull'identità del contenuto PHP o del nome della tabella.

```text theme={null}
2026_10_02_120001_create_courier_deliveries_table
2026_10_03_090001_create_courier_deliveries_table
```

Questi due sono nomi di migrazione diversi. Anche se il primo è stato eseguito, quello storico non basta a considerare eseguito il secondo.

<Warning>
  Non rieseguire incondizionatamente il comando di pubblicazione della prima installazione a ogni aggiornamento del pacchetto e non rendere `--force` parte della procedura standard. Oltre a sovrascrivere le modifiche ai file pubblicati, potresti aggiungere operazioni duplicate a causa della modifica della data.
</Warning>

## Implementare il caricamento diretto

Se vuoi che le migrazioni del pacchetto vengano eseguite così come sono, registra un percorso di ricerca. In questo approccio non si aggiunge alcuna pubblicazione degli stessi file.

```php theme={null}
<?php

namespace Acme\Courier;

use Illuminate\Support\ServiceProvider;

class CourierServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        $this->loadMigrationsFrom(__DIR__.'/../database/migrations');
    }
}
```

`loadMigrationsFrom()` chiama `path()` quando il Migrator viene risolto. `Migrator::path()` elimina i percorsi di ricerca duplicati, mentre `getMigrationFiles()` indicizza i file trovati per nome di migrazione e li ordina in base a tale nome.

Quando l'utente aggiorna il pacchetto, i nuovi file vengono considerati dal successivo `migrate`. Non rinominare i file esistenti: per le nuove modifiche allo schema aggiungi nuovi file. Per evitare conflitti con altri pacchetti, includi anche il nome della funzionalità, come in `create_courier_deliveries_table`. File con lo stesso nome producono la stessa chiave e non vengono eseguiti entrambi in modo indipendente.

<Warning>
  Passare dalla pubblicazione al caricamento diretto non è una semplice riscrittura del provider. Se lo storico di esecuzione dell'utente è registrato con i nomi assegnati in fase di pubblicazione, questi non corrispondono ai nomi originali nel pacchetto. Serve una procedura di migrazione che tenga conto dello storico degli utenti esistenti, dei file pubblicati e del rollback.
</Warning>

## Distribuire le modifiche allo schema agli utenti esistenti

Per esempio, per aggiungere un codice di tracciamento alla tabella delle spedizioni, non modificare il `create_courier_deliveries_table` già pubblicato, ma aggiungi un nuovo file dedicato alla modifica. Anche se modifichi la migrazione di creazione esistente, la modifica non verrà eseguita per gli utenti che l'hanno già eseguita.

```php database/migrations/2026_10_02_000000_add_tracking_code_to_courier_deliveries_table.php theme={null}
<?php

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

return new class extends Migration
{
    public function up(): void
    {
        Schema::table('courier_deliveries', function (Blueprint $table) {
            $table->string('tracking_code')->nullable();
        });
    }

    public function down(): void
    {
        Schema::table('courier_deliveries', function (Blueprint $table) {
            $table->dropColumn('tracking_code');
        });
    }
};
```

Poiché l'esempio aggiunge una colonna a una tabella con righe esistenti, qui la colonna è nullable. Se devi renderla obbligatoria o popolare i dati esistenti, progetta separatamente quella procedura e il relativo ordine di esecuzione.

Con la pubblicazione, prepara una procedura di aggiornamento che confronti i file già pubblicati dall'utente e distribuisca **solo i file aggiunti in questa release**. Puoi anche prevedere un tag di pubblicazione dedicato ai nuovi file, ma se l'aggiornamento della data è attivo valgono le stesse cautele per l'esecuzione ripetuta di quel tag. Non basare la procedura di aggiornamento sulla semplice riesecuzione del tag della prima installazione.

Con il caricamento diretto, il codice aggiornato rileva automaticamente i nuovi file. In entrambi i casi, la sola presenza dei file non modifica il database, quindi indica chiaramente nelle note di rilascio che è necessario eseguire le migrazioni.

## Verifiche prima del rilascio

Oltre ai test del database del pacchetto, verifica le procedure di pubblicazione e aggiornamento in un'applicazione che lo usa. Caricare direttamente le migrazioni nei test non equivale a verificare la pubblicazione, in cui i nomi dei file cambiano.

* Una prima installazione su un database vuoto crea le tabelle necessarie.
* L'aggiornamento a partire dal database e dallo storico di esecuzione di una release precedente applica solo le nuove modifiche.
* Controllando l'elenco dei file dopo aver ripetuto lo stesso comando di pubblicazione, la procedura di aggiornamento non genera duplicati.
* La procedura tiene conto dell'aggiornamento della data attivo o disattivo e delle modifiche ai file pubblicati.
* Verifica il rollback delle nuove migrazioni e il loro ordine di esecuzione rispetto alle altre migrazioni dell'applicazione.

## Pagine correlate

<Columns cols={2}>
  <Card title="Migrazioni" icon="database" href="/it/migrations">
    Le basi di definizione dello schema, storico di esecuzione e rollback.
  </Card>

  <Card title="Test dei pacchetti" icon="flask" href="/it/advanced/package-testing">
    Testa il service provider e il database del pacchetto.
  </Card>

  <Card title="Merge e cache della configurazione dei pacchetti" icon="sliders" href="/it/advanced/package-config-merging">
    Procedure di aggiornamento che tengono conto della configurazione dell'utente e della relativa cache.
  </Card>

  <Card title="Gestione della compatibilità tra versioni" icon="code-branch" href="/it/advanced/package-versioning">
    Collega le procedure di aggiornamento e le modifiche di compatibilità alla politica di rilascio.
  </Card>
</Columns>

## Fonti primarie consultate

* [Documentazione ufficiale di Laravel: migrazioni dei pacchetti](https://github.com/laravel/docs/blob/156fc7fde114548640e13c39aa79b991291c3f91/packages.md#migrations)
* [ServiceProvider: registrazione delle risorse pubblicabili e dei percorsi di ricerca](https://github.com/laravel/framework/blob/v13.34.0/src/Illuminate/Support/ServiceProvider.php)
* [VendorPublishCommand: copia e modifica dei timestamp](https://github.com/laravel/framework/blob/v13.34.0/src/Illuminate/Foundation/Console/VendorPublishCommand.php)
* [Migrator: rilevamento dei file e determinazione delle migrazioni non eseguite](https://github.com/laravel/framework/blob/v13.34.0/src/Illuminate/Database/Migrations/Migrator.php)
* [Applicazione standard di Laravel 13: configurazione del database](https://github.com/laravel/laravel/blob/06d016a364a37430eec9cbc52209adce3d7667ce/config/database.php)


## Related topics

- [Sviluppo di pacchetti Laravel](/it/advanced/package-development.md)
- [Argomenti avanzati](/it/advanced/index.md)
- [Aggiornamento da Laravel 10 a 11](/it/blog/upgrade-10-to-11.md)
- [Laravel AI SDK](/it/ai-sdk.md)
- [Pinning e sicurezza delle GitHub Actions](/it/advanced/github-actions-pinning.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.