v13.40.0. Para lo básico de la configuración de conexiones, consulta Configuración de la base de datos, y para la carga de providers, Descubrimiento de paquetes.
Elegir el punto de extensión
La creación de conexiones de base de datos ofrece puntos de extensión con alcances distintos.
El valor devuelto por el callback que pasas a
DB::extend() no es un PDO ni un Query Builder, sino un Illuminate\Database\Connection. DatabaseManager::configure() exige esta clase.
La extensión por nombre de conexión tiene prioridad sobre el nombre de driver
DatabaseManager::makeConnection() obtiene la configuración y luego elige la lógica de creación en el siguiente orden.
DB::extend('reporting', ...)se aplica adatabase.connections.reporting.DB::extend('mysql', ...)se aplica a las conexiones cuyodriveresmysqly que no tienen una extensión por nombre de conexión.- Ambos usan el mismo registro de extensiones. Ten en cuenta también los conflictos entre nombres de conexión y nombres de driver, y usa nombres propios del paquete.
extend()no crea el array de configuración. Si solo registras la extensión y no existe la configuración de la conexión con ese nombre, se lanzará una excepción.
Seleccionar explícitamente un nombre de driver propio
El siguiente es un ejemplo mínimo que conecta el nombre propioacme-sqlite con la creación de una conexión SQLite estándar. No es un ejemplo de implementación de un nuevo protocolo de BD ni de un dialecto SQL. Muestra la frontera entre el registro y la selección al distribuir un adaptador propio.
Se asume una estructura en la que Acme\DatabaseBridge\ corresponde a src/ mediante PSR-4 de Composer, y el archivo se coloca en src/DatabaseBridgeServiceProvider.php.
db.factory es el binding del ConnectionFactory compartido por Laravel. Como se llama directamente al Factory estándar, no se vuelve a la selección de extensiones del DatabaseManager y se puede reutilizar la creación diferida del PDO y de la Connection de SQLite.
Este callback se ejecuta la primera vez que se resuelve la conexión. El boot() del provider solo registra la lógica de creación y no ejecuta pruebas de conexión ni migraciones. Como provider normal no diferido, haz que se cargue antes de que la conexión objetivo se resuelva por primera vez.
La aplicación que lo usa añade la conexión al array connections existente en config/database.php. No cambia el valor predeterminado default.
acme_reports, no el nombre de driver acme-sqlite. En el ejemplo, driver se convierte a sqlite antes de pasarlo al Factory, por lo que getDriverName() tras la creación también devuelve sqlite.
Reemplazar por una subclase de Connection es otro alcance
Para reemplazar la propia clase Connection de un driver existente, existeConnection::resolverFor(). El callback puede recibir una Closure que crea el PDO de forma diferida, en lugar de un PDO ya conectado.
Sin embargo, este registro se guarda en una propiedad estática de la clase Connection. Si lo registras para sqlite, afectará a todas las conexiones SQLite nuevas creadas por el Factory estándar, incluido el ejemplo acme-sqlite anterior. No puede tratarse como un reemplazo para un único nombre de conexión.
- En el callback, devuelve una subclase de Connection para la BD objetivo. Con la Connection base por sí sola no se conservan el Grammar, el Processor y demás elementos propios de la BD.
- El Factory separa
createConnector()decreateConnection(). Registrar soloresolverFor()no proporciona un conector PDO para un driver desconocido. - Si el resolver propio de
DB::extend()no usa el Factory estándar, tampoco pasa por la comprobación deresolverFor()dentro del Factory. - Volver a registrar el mismo driver lo sobrescribe. Comprueba los conflictos con otros paquetes y que no se arrastre entre pruebas dentro del mismo proceso PHP.
DB::extend() con un nombre de conexión o de driver propio.
Distinguir reconnect y purge
El DatabaseManager retiene las Connection creadas por nombre de conexión. Aunque cambies la configuración o el resolver, los cambios no se reflejan automáticamente en las conexiones ya creadas.
En particular,
reconnect() no es una API que reemplace por completo la clase o el array de configuración de la Connection retenida. Si quieres reflejar cambios en la clase extendida o en la configuración de la conexión, ejecuta purge() en un momento seguro sin transacciones en curso y luego obtén una nueva conexión.
Probar el registro y la creación del paquete
Con Orchestra Testbench, carga el provider y selecciona realmente el driver propio. El siguiente es un ejemplo detests/DatabaseBridgeTest.php. El entorno de ejecución necesita PDO y el driver de SQLite.
:memory: pierde su contenido al desconectarse, esta prueba no espera que se conserven tablas ni datos. En un paquete real, añade también lo siguiente:
- Que el resolver por nombre de conexión tenga prioridad sobre el resolver por nombre de driver.
- Que volver a registrar el mismo nombre y
forgetExtension()no reemplacen las Connection ya creadas. - Las excepciones cuando falta configuración obligatoria y el comportamiento cuando falla la conexión.
- Las funciones que te comprometes a ofrecer, como migraciones, transacciones o separación read/write en las BD compatibles.
- Que el registro y el estado de las conexiones no se mezclen en workers de larga duración ni al combinarse con varios paquetes.
Puntos de comprobación para el mantenimiento
- ¿Se activa mediante un nombre propio (opt-in) sin sobrescribir en silencio la conexión predeterminada ni los drivers integrados?
- ¿Evitas meter Closures u objetos de conexión en la caché de configuración y colocas la lógica de creación en el provider?
- ¿Gestionas los destinos de conexión y las credenciales como configuración de aplicación de confianza?
- ¿Has vuelto a comprobar los argumentos de
extend(), el orden de creación del Factory y lo que transfierereconnect()en las versiones de Laravel soportadas? - ¿Indicas a los usuarios el procedimiento de regeneración tras cambiar la configuración y el reinicio de los workers?
Páginas relacionadas
- Desarrollo de paquetes
- Diseño del ciclo de vida de los servicios de paquetes
- Fusión y caché de la configuración de paquetes
- Publicación y actualización de migraciones de paquetes
Fuentes primarias consultadas
- Documentación oficial de Laravel: base de datos y múltiples conexiones
- Documentación oficial de Laravel: service providers de paquetes
- DatabaseManager: orden de creación, registro de extensiones, retención de conexiones y reconexión
- ConnectionFactory: creación diferida del PDO y resolver de Connection
- Connection: resolverFor y getResolver
- DatabaseServiceProvider: registro de db y db.factory