php - ejemplo - Laravel 4: Aplicación de inquilinos múltiples, cada inquilino es su propia base de datos y una base de datos global
select2 ejemplo (5)
Actualmente tengo una aplicación que aloja varios inquilinos escritos en CodeIgniter. Pero realmente amo a Laravel 4 y me gustaría comenzar a migrar la aplicación a Laravel.
Aquí está la configuración actual:
- Cada inquilino tiene su propia base de datos.
- Solo hay un conjunto de archivos de aplicación.
- Cuando creamos un nuevo inquilino, se crea una nueva base de datos y se ejecuta una secuencia de comandos de instalación y la base de datos se incluye con información inicial.
- Cada inquilino también tiene su propio subdominio. Así es como podemos detectar qué base de datos usar.
- Hay una base de datos principal que contiene información y usuarios de inquilinos y algunas otras tablas generales.
- Cuando se necesita una actualización de esquema, simplemente creamos un script de actualización que se ejecutará para cada inquilino. Esto sucede a través de un script CLI especialmente codificado para Codeigniter
En Codeigniter es relativamente fácil iniciar y finalizar nuevas conexiones de bases de datos.
Con Laravel tengo los siguientes problemas / preguntas.
- ¿Cómo comenzaría / terminaría las conexiones de la base de datos sobre la marcha?
- Me gustaría utilizar migraciones, pero me gustaría ejecutarlas para cada inquilino. Las migraciones actualmente solo se ejecutan en la conexión de base de datos "principal". Y solo se ejecuta una vez.
- Lo mismo ocurre con la siembra ..
Estos son mis principales problemas, tengo otras cosas menores, pero se pueden solucionar.
Con suerte, alguien puede arrojar algo de luz ..
1) Puede definir múltiples conexiones con nombre en su archivo de configuración database.php
''connections'' => array(
''tenant1'' => array(
...
),
''tenant2'' => array(
...
),
Entonces puedes elegir cuál usar con algo como esto.
$something = DB::connection(''tenant1'')->select(...);
2) Esta no es una solución completa, ya que creo que requerirá algunas intrusiones en el núcleo, pero puede elegir en qué conexión ejecutar una migración. Tal vez podría iterar a través de su lista de inquilinos y ejecutarla en todos ellos.
Schema::connection(''tenant1'')->create(''users'', function($table)
3) Desafortunadamente, no creo que seeding soporte conexiones múltiples todavía. Es posible que deba desplegar su propia funcionalidad de siembra.
Puede crear 1 base de datos con las credenciales de la base de datos del inquilino y configurarlas dinámicamente en su aplicación:
$tenant = Tenant::where(''username'', ''='', $username)->first();
Config::set(''database.connections.tenant.username'', $tenant->db_username);
Config::set(''database.connections.tenant.password'', $tenant->db_password);
Config::set(''database.connections.tenant.database'', $tenant->db_database);
Esto requerirá crear 2 conexiones en su archivo database.php. (por ejemplo, aplicación e inquilino) y especifique en su modelo qué base de datos usar (1 para el almacenamiento de inquilinos, 1 para la base de datos específica del inquilino)
Y probablemente cree una ruta / script para crear / actualizar las tablas. No estoy seguro acerca de las migraciones con múltiples bases de datos.
Puede crear conexiones de bases de datos dinámicas en laravel con la siguiente sintaxis
Config::set(''database.connections.key'', array(
''driver'' => ''mysql'',
''host'' => ''localhost'',
''database'' => ''dbname'',
''username'' => ''dbuser'',
''password'' => ''dbpass'',
''charset'' => ''utf8'',
''collation'' => ''utf8_unicode_ci'',
''prefix'' => '''',
));
Con esa DB::connection(''key''); would just work.
DB::connection(''key''); would just work.
Recientemente me encontré con un problema similar, tuve que usar diferentes bases de datos para varios modelos.
He encontrado lo siguiente para hacer el truco.
- En app / config / database.php agrega una nueva conexión MY_NEW_CONNECTION
- Para la nueva conexión, establezca el nombre de la base de datos a lo que sea
En su filters.php o routes.php o el método __construct del controlador agregue lo siguiente:
$ db = ''obtener el nombre de su base de datos''; Config :: set (''database.connections.MY_NEW_CONNECTION.database'', $ db); DB :: setDefaultConnection (''MY_NEW_CONNECTION'');
Solo estoy dando un vistazo a esto, así que ten cuidado :) La clase DatabaseManager, que se usa cada vez que llamas a DB, tiene y extiende el método. Aquí está el enlace a la fuente . El método DB :: connection () debería devolver una instancia de Illuminate/Database/Connection . De todo esto, crearía una nueva conexión de usuario de la siguiente manera:
$user = Auth::user();
DB::extend($user->username, function() use ($user) {
// $pdo = new PDO(); set this up how you see fit
return new Illuminate/Database/Connection($pdo, $user->databaseName, $tablePrefix);
});
Personalmente, agregaría un nuevo método a cada usuario, User :: databaseConnection (), y lo llamaré cuando extienda el DatabaseManager.
DB::extend($user->username, function() use ($user) {
return $user->databaseConnection();
});
A través de su aplicación, debe poder llamar a la conexión de un usuario registrado a través de:
DB::connection(Auth::user()->username);
Actualizar
Según la frecuencia y el momento en que llame a la conexión del inquilino, es posible que desee utilizar el contenedor del COI.
App::bind(''tenantDB'', function()
{
return DB::connection(Auth::user()->username);
});
App::make(''tenantDB'')->insert(...);
Me olvidé de las migraciones y la siembra. Para migraciones, puede establecer la ruta del archivo
php artisan migrate:make foo --path=app/migrations
Entonces, si usa la clase Config para establecer la base de datos predeterminada o DB :: setDefaultConnection ($ username), supondría que todas las migraciones y siembra se realizarán para la conexión actual. Cuando se complete ese proceso, puede volver a la base de datos principal.
Actualización 2
Los desarrolladores de Laravel son increíbles y definitivamente debería tener la urgencia de comprobar esto más temprano que tarde. Puede hacer migraciones y sembrar en cualquier conexión de base de datos que haya creado.
artisan migrate --database=''userConnectionName''
artisan db:seed --database=''userConnectionName''
En cuanto a la respuesta de Barry, probablemente sea mucho más simple que extender el DatabaseManager.
Si desea ver todas las opciones para estos comandos simplemente ejecute:
artisan help migrate
artisan help db:seed