Vai al contenuto principale
Per estendere le connessioni al database da un pacchetto, separa la registrazione del metodo di creazione dalla selezione della connessione da usare. Progetta il pacchetto in modo che la semplice installazione non sostituisca la connessione predefinita dell’applicazione né tutte le connessioni MySQL. Questa pagina esamina i sorgenti ufficiali di Laravel Framework v13.40.0. Per le basi della configurazione delle connessioni consulta Configurazione del database, per il caricamento dei provider consulta Package auto-discovery.

Scegliere il punto di estensione

Il processo di creazione del database offre punti di estensione con ambiti diversi. Il valore restituito dal callback passato a DB::extend() non è un PDO né un Query Builder, ma una Illuminate\Database\Connection. È DatabaseManager::configure() a richiedere questa classe.
L’extend() del database non segue la stessa convenzione di chiamata del comune Illuminate\Support\Manager. Il primo argomento del callback non è il container dell’applicazione, ma l’array di configurazione della connessione. Non riutilizzare così come sono gli esempi di estensione di altri driver.

L’estensione per nome della connessione ha la precedenza sul nome del driver

DatabaseManager::makeConnection(), dopo aver ottenuto la configurazione, sceglie il metodo di creazione nel seguente ordine.
  • DB::extend('reporting', ...) si applica a database.connections.reporting.
  • DB::extend('mysql', ...) si applica alle connessioni con driver uguale a mysql che non hanno un’estensione per nome della connessione.
  • Entrambi usano lo stesso registro delle estensioni. Considerando anche le collisioni tra nomi di connessione e nomi di driver, usa nomi specifici del pacchetto.
  • extend() non crea l’array di configurazione. Registrando solo l’estensione, se non esiste la configurazione di una connessione con il nome indicato si verifica un’eccezione.

Selezionare esplicitamente un nome di driver personalizzato

Di seguito un esempio minimo che collega il nome personalizzato acme-sqlite alla creazione di una connessione SQLite standard. Non è un esempio di implementazione di un nuovo protocollo di DB o di un dialetto SQL. Mostra il confine tra registrazione e selezione quando si distribuisce un adattatore personalizzato. Si presuppone una struttura in cui Acme\DatabaseBridge\ corrisponde a src/ tramite PSR-4 di Composer, e il file si trova in src/DatabaseBridgeServiceProvider.php.
db.factory è il binding della ConnectionFactory condivisa da Laravel. Poiché chiama direttamente la Factory standard, non torna alla selezione delle estensioni del DatabaseManager e può riutilizzare la creazione lazy del PDO e la creazione della Connection di SQLite. Questo callback viene eseguito alla prima risoluzione della connessione. Il boot() del provider si limita a registrare il metodo di creazione e non esegue test di connessione né migrazioni. Come normale provider non differito, fallo caricare prima che la connessione interessata venga risolta per la prima volta. L’applicazione utilizzatrice aggiunge la connessione all’array connections esistente in config/database.php. Il valore predefinito default non viene modificato.
Prepara in anticipo il file SQLite e verifica i permessi di scrittura prima dell’uso. Non progettare il pacchetto in modo che crei il file al semplice caricamento.
Ciò che l’utente passa è il nome della connessione acme_reports, non il nome del driver acme-sqlite. Nell’esempio, driver viene convertito in sqlite prima di essere passato alla Factory, quindi anche getDriverName() dopo la creazione restituisce sqlite.
Se dall’interno del resolver richiami DB::connection($name), torni alla creazione della stessa connessione non ancora conservata. Per evitare la ricorsione, crea la Connection con la Factory o con un adattatore personalizzato.

La sostituzione con una sottoclasse di Connection ha un ambito diverso

Per sostituire la classe Connection stessa di un driver esistente, esiste Connection::resolverFor(). Al callback può essere passata una Closure che crea il PDO in modo lazy, anziché un PDO già connesso. Tuttavia, questa registrazione viene conservata in una proprietà statica della classe Connection. Registrandola per sqlite, influisce su tutte le nuove connessioni SQLite create dalla Factory standard, incluso l’esempio acme-sqlite qui sopra. Non può essere trattata come la sostituzione di un singolo nome di connessione.
  • Nel callback restituisci una sottoclasse di Connection per il DB interessato. Con la sola Connection di base non si conservano Grammar, Processor e altri elementi specifici del DB.
  • La Factory separa createConnector() e createConnection(). La sola registrazione con resolverFor() non fornisce anche un connettore PDO per driver sconosciuti.
  • Se il resolver personalizzato di DB::extend() non usa la Factory standard, non passa nemmeno per il controllo di resolverFor() all’interno della Factory.
  • Una nuova registrazione per lo stesso driver la sovrascrive. Verifica i conflitti con altri pacchetti e il trascinamento tra test nello stesso processo PHP.
I pacchetti che vogliono limitare l’impatto dovrebbero valutare prima DB::extend() con un nome di connessione o di driver specifico.

Distinguere reconnect e purge

Il DatabaseManager conserva le Connection create per nome della connessione. Anche modificando la configurazione o il resolver, le modifiche non si riflettono automaticamente sulle connessioni già create. In particolare, reconnect() non è un’API che sostituisce integralmente la classe o l’array di configurazione della Connection conservata. Per riflettere modifiche alla classe di estensione o alla configurazione della connessione, esegui purge() in un momento sicuro senza transazioni in corso, quindi ottieni una nuova connessione.
purge() non sostituisce con quella nuova i riferimenti alla Connection conservati da altri servizi o variabili. Inoltre, ::read, ::write e ::direct nel nome della connessione sono chiavi di conservazione separate: non dare per scontato che eseguire il purge del nome base le elimini tutte insieme.Non riscrivere con leggerezza la configurazione di una connessione condivisa in esecuzione, ad esempio per cambiare tenant. Nei worker di lunga durata, verifica non solo l’aggiornamento della cache di configurazione, ma anche il riavvio dei processi e l’impatto sui servizi conservati.

Testare la registrazione e la creazione nel pacchetto

Con Orchestra Testbench carica il provider e seleziona effettivamente il driver personalizzato. Di seguito un esempio di tests/DatabaseBridgeTest.php. L’ambiente di esecuzione richiede PDO e il driver SQLite.
Con :memory: il contenuto va perso alla disconnessione, quindi questo test non si aspetta che tabelle o dati vengano conservati. In un pacchetto reale, aggiungi anche:
  • Che il resolver del nome della connessione abbia la precedenza su quello del nome del driver.
  • Che una nuova registrazione con lo stesso nome e forgetExtension() non sostituiscano le Connection già create.
  • L’eccezione quando manca una configurazione obbligatoria e il comportamento in caso di connessione fallita.
  • Le funzionalità che ti impegni a fornire, come migrazioni, transazioni e separazione read/write sui DB supportati.
  • Che registrazioni e stati delle connessioni non si mescolino con worker di lunga durata o con l’uso insieme ad altri pacchetti.

Punti da verificare durante la manutenzione

  • Si attiva tramite un nome personalizzato (opt-in) senza sovrascrivere silenziosamente la connessione predefinita o i driver integrati?
  • Evita di inserire Closure o oggetti di connessione nella cache della configurazione, collocando il processo di creazione nel provider?
  • Destinazioni di connessione e credenziali sono gestite come configurazione affidabile dell’applicazione?
  • Hai ricontrollato, sulle versioni di Laravel supportate, gli argomenti di extend(), l’ordine di creazione della Factory e gli elementi trasferiti da reconnect()?
  • Indichi agli utenti la procedura di ricreazione dopo le modifiche alla configurazione e il riavvio dei worker?

Pagine correlate

Fonti primarie consultate

Ultima modifica il 3 novembre 2026