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’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 adatabase.connections.reporting.DB::extend('mysql', ...)si applica alle connessioni condriveruguale amysqlche 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 personalizzatoacme-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.
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.
La sostituzione con una sottoclasse di Connection ha un ambito diverso
Per sostituire la classe Connection stessa di un driver esistente, esisteConnection::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()ecreateConnection(). La sola registrazione conresolverFor()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 diresolverFor()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.
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.
Testare la registrazione e la creazione nel pacchetto
Con Orchestra Testbench carica il provider e seleziona effettivamente il driver personalizzato. Di seguito un esempio ditests/DatabaseBridgeTest.php. L’ambiente di esecuzione richiede PDO e il driver SQLite.
: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 dareconnect()? - Indichi agli utenti la procedura di ricreazione dopo le modifiche alla configurazione e il riavvio dei worker?
Pagine correlate
- Sviluppo di pacchetti
- Progettare il ciclo di vita dei servizi nei pacchetti
- Unione e cache della configurazione dei pacchetti
- Pubblicazione e aggiornamento delle migrazioni dei pacchetti
Fonti primarie consultate
- Documentazione ufficiale di Laravel: database e connessioni multiple
- Documentazione ufficiale di Laravel: service provider dei pacchetti
- DatabaseManager: ordine di creazione, registrazione delle estensioni, conservazione e riconnessione delle connessioni
- ConnectionFactory: creazione lazy del PDO e resolver della Connection
- Connection: resolverFor e getResolver
- DatabaseServiceProvider: registrazione di db e db.factory