Currently i have a application that hosts multiple tenants written in CodeIgniter. But i am really loving Laravel 4 and i would like to start migrating the application to Laravel.
目前,我有一个应用程序,它托管使用CodeIgniter编写的多个租户。但是我真的很喜欢Laravel 4,我想把这个应用程序移植到Laravel。
Here is the current setup:
以下是当前的设置:
- Each tenant has it's own database.
- 每个租户都有自己的数据库。
- There is just one set of application files.
- 只有一组应用程序文件。
- When we create a new tenant a new database is created and an install script is run and the database is seeded with some initial information.
- 当我们创建一个新的承租者时,将创建一个新的数据库,并运行一个安装脚本,并向数据库播种一些初始信息。
- Each tenant also has it's own subdomain. That is how we can detect which database to use.
- 每个租户也有自己的子域。这就是我们可以检测使用哪个数据库的方法。
- There is a main database that holds tenant information and users and some other general tables.
- 有一个主数据库保存租户信息、用户和其他一些通用表。
- When a schema update is needed we just create an update script that will run for each tenant. This happens via a specially coded CLI script for Codeigniter
- 当需要模式更新时,我们只需创建一个更新脚本,该脚本将为每个租户运行。这是通过为Codeigniter编写的特殊CLI脚本实现的
In Codeigniter it's relatively easy to start and end new database connections.
在Codeigniter中,启动和结束新的数据库连接相对容易。
With Laravel i have the following issues/questions.
我有以下的问题/问题。
- How would you start/end database connections on the fly?
- 如何动态启动/结束数据库连接?
- I would like to use Migrations but i would like to run them for each tenant. Migrations currently only run on the "main" database connection. And it only runs once.
- 我希望使用迁移,但我希望为每个租户运行它们。迁移目前只在“主”数据库连接上运行。它只运行一次。
- Same goes for seeding..
- 同样适用于播种。
These are my main issues, i have some other minor stuff but those can be worked around.
这些是我的主要问题,我还有一些其他的小问题,但这些都是可以解决的。
Hopefully someone can shed some light..
希望有人能给我们一些启示。
5 个解决方案
#1
23
I'm just taking a stab at this, so be warned :) The DatabaseManager class, which is used whenever you call DB, has and extend method. Here's the link to the source. The DB::connection() method should return an instance of Illuminate\Database\Connection. From all this, I would create a new user connection as follows:
我只是想尝试一下,所以请注意:)DatabaseManager类具有和扩展方法,无论何时调用DB都使用它。这是到源代码的链接。方法应该返回一个实例,说明数据库\连接。由此,我将创建一个新的用户连接,如下所示:
$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);
});
Personally, I would add a new method to each user, User::databaseConnection(), and call that when I extend the DatabaseManager.
就我个人而言,我将向每个用户user:::databaseConnection()添加一个新方法,并在扩展DatabaseManager时调用该方法。
DB::extend($user->username, function() use ($user) {
return $user->databaseConnection();
});
Through out your application you should be able to call a registered user's connection via:
通过您的应用程序,您应该能够通过以下方式调用注册用户的连接:
DB::connection(Auth::user()->username);
Update
更新
Depending on how often and when you'd be calling the tenant connection, you may want to use the IOC container.
根据调用租户连接的频率和时间,您可能希望使用IOC容器。
App::bind('tenantDB', function()
{
return DB::connection(Auth::user()->username);
});
App::make('tenantDB')->insert(...);
I forgot about migrations and seeding. For migrations, you can set the file path
我忘记了迁徙和播种。对于迁移,可以设置文件路径
php artisan migrate:make foo --path=app/migrations
So if you use the Config class to set the default database or DB::setDefaultConnection($username), I'd assume all migrations and seeding will be done for the current connection. When that process if complete you can switch back to you main database.
因此,如果您使用配置类来设置默认的数据库或DB::setDefaultConnection($username),我假设所有迁移和播种都将在当前连接中完成。当该过程完成时,您可以切换回主数据库。
Update 2
更新2
The laravel developers are amazing and I should have definitely got the urge to check this out sooner than later. You can do migrations and seed on any database connection you've created.
laravel的开发人员非常棒,我应该尽快检查一下。您可以在创建的任何数据库连接上进行迁移和种子。
artisan migrate --database='userConnectionName'
artisan db:seed --database='userConnectionName'
Looking at Barry's answer, that is probably a good deal simpler than extending the DatabaseManager.
看看Barry的回答,这可能比扩展DatabaseManager简单得多。
If you want to see all the options for these commands just run:
如果您想查看这些命令的所有选项,请运行:
artisan help migrate
artisan help db:seed
#2
6
You can create 1 database with the tenant database credentials, and dynamically set them in your app:
您可以使用租户数据库凭证创建一个数据库,并在应用程序中动态设置它们:
$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);
This will require to create 2 connections in your database.php file. (for instance app and tenant) and specify in your model which database to use (1 for the storing of tenants, 1 for the tenant specific database)
这将需要在数据库中创建两个连接。php文件。(例如app和租户)并在模型中指定使用哪个数据库(1用于存储租户,1用于特定租户数据库)
And probably create a route/script to create/update the tables. Not sure about migrations with multiple databases.
并可能创建一个路由/脚本来创建/更新表。不确定有多个数据库的迁移。
#3
4
You can create dynamic DB connections in laravel with following syntax
您可以使用以下语法创建动态数据库连接。
Config::set('database.connections.key', array(
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'dbname',
'username' => 'dbuser',
'password' => 'dbpass',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
));
With that DB::connection('key'); would just work.
DB::连接(“关键”);只会工作。
#4
0
I've recently encountered a similar problem, had to use different Databases for several models.
我最近遇到了一个类似的问题,必须为几个模型使用不同的数据库。
I've found the following to do the trick.
我找到了下面的方法。
- In app/config/database.php add a new connection MY_NEW_CONNECTION
- 在app / config /数据库。php添加一个新的连接MY_NEW_CONNECTION
- For the new connection, set the database name to whatever
- 对于新连接,将数据库名称设置为任意。
-
In your filters.php or routes.php or controller's __construct method add the following:
在你的过滤器。php或路线。php或controller的__construct方法添加如下内容:
$db = 'get your database name'; Config::set('database.connections.MY_NEW_CONNECTION.database',$db); DB::setDefaultConnection('MY_NEW_CONNECTION');
$db = '获取数据库名称';配置:设置(database.connections.MY_NEW_CONNECTION.database,$ db);DB:setDefaultConnection(“MY_NEW_CONNECTION”);
#5
-3
1) You can define multiple named connections in your database.php config file
1)可以在数据库中定义多个命名连接。php配置文件
'connections' => array(
'tenant1' => array(
...
),
'tenant2' => array(
...
),
Then you can choose which one to use with something like this.
然后你可以选择用哪一个像这样的东西。
$something = DB::connection('tenant1')->select(...);
2) This isn't a full solution as I think it will require some hacking on the core, but you can choose which connection to run a migration on. Maybe you could iterate through your list of tenants and run it on all of them.
2)这不是一个完整的解决方案,因为我认为它需要对内核进行一些修改,但是您可以选择在哪个连接上运行迁移。也许您可以遍历您的租户列表,并在所有租户上运行它。
Schema::connection('tenant1')->create('users', function($table)
3) Unfortunately, I don't think seeding supports multiple connections yet. You might have to roll your own seeding functionality.
不幸的是,我认为播种还不支持多种连接。您可能需要滚动自己的播种功能。
#1
23
I'm just taking a stab at this, so be warned :) The DatabaseManager class, which is used whenever you call DB, has and extend method. Here's the link to the source. The DB::connection() method should return an instance of Illuminate\Database\Connection. From all this, I would create a new user connection as follows:
我只是想尝试一下,所以请注意:)DatabaseManager类具有和扩展方法,无论何时调用DB都使用它。这是到源代码的链接。方法应该返回一个实例,说明数据库\连接。由此,我将创建一个新的用户连接,如下所示:
$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);
});
Personally, I would add a new method to each user, User::databaseConnection(), and call that when I extend the DatabaseManager.
就我个人而言,我将向每个用户user:::databaseConnection()添加一个新方法,并在扩展DatabaseManager时调用该方法。
DB::extend($user->username, function() use ($user) {
return $user->databaseConnection();
});
Through out your application you should be able to call a registered user's connection via:
通过您的应用程序,您应该能够通过以下方式调用注册用户的连接:
DB::connection(Auth::user()->username);
Update
更新
Depending on how often and when you'd be calling the tenant connection, you may want to use the IOC container.
根据调用租户连接的频率和时间,您可能希望使用IOC容器。
App::bind('tenantDB', function()
{
return DB::connection(Auth::user()->username);
});
App::make('tenantDB')->insert(...);
I forgot about migrations and seeding. For migrations, you can set the file path
我忘记了迁徙和播种。对于迁移,可以设置文件路径
php artisan migrate:make foo --path=app/migrations
So if you use the Config class to set the default database or DB::setDefaultConnection($username), I'd assume all migrations and seeding will be done for the current connection. When that process if complete you can switch back to you main database.
因此,如果您使用配置类来设置默认的数据库或DB::setDefaultConnection($username),我假设所有迁移和播种都将在当前连接中完成。当该过程完成时,您可以切换回主数据库。
Update 2
更新2
The laravel developers are amazing and I should have definitely got the urge to check this out sooner than later. You can do migrations and seed on any database connection you've created.
laravel的开发人员非常棒,我应该尽快检查一下。您可以在创建的任何数据库连接上进行迁移和种子。
artisan migrate --database='userConnectionName'
artisan db:seed --database='userConnectionName'
Looking at Barry's answer, that is probably a good deal simpler than extending the DatabaseManager.
看看Barry的回答,这可能比扩展DatabaseManager简单得多。
If you want to see all the options for these commands just run:
如果您想查看这些命令的所有选项,请运行:
artisan help migrate
artisan help db:seed
#2
6
You can create 1 database with the tenant database credentials, and dynamically set them in your app:
您可以使用租户数据库凭证创建一个数据库,并在应用程序中动态设置它们:
$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);
This will require to create 2 connections in your database.php file. (for instance app and tenant) and specify in your model which database to use (1 for the storing of tenants, 1 for the tenant specific database)
这将需要在数据库中创建两个连接。php文件。(例如app和租户)并在模型中指定使用哪个数据库(1用于存储租户,1用于特定租户数据库)
And probably create a route/script to create/update the tables. Not sure about migrations with multiple databases.
并可能创建一个路由/脚本来创建/更新表。不确定有多个数据库的迁移。
#3
4
You can create dynamic DB connections in laravel with following syntax
您可以使用以下语法创建动态数据库连接。
Config::set('database.connections.key', array(
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'dbname',
'username' => 'dbuser',
'password' => 'dbpass',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
));
With that DB::connection('key'); would just work.
DB::连接(“关键”);只会工作。
#4
0
I've recently encountered a similar problem, had to use different Databases for several models.
我最近遇到了一个类似的问题,必须为几个模型使用不同的数据库。
I've found the following to do the trick.
我找到了下面的方法。
- In app/config/database.php add a new connection MY_NEW_CONNECTION
- 在app / config /数据库。php添加一个新的连接MY_NEW_CONNECTION
- For the new connection, set the database name to whatever
- 对于新连接,将数据库名称设置为任意。
-
In your filters.php or routes.php or controller's __construct method add the following:
在你的过滤器。php或路线。php或controller的__construct方法添加如下内容:
$db = 'get your database name'; Config::set('database.connections.MY_NEW_CONNECTION.database',$db); DB::setDefaultConnection('MY_NEW_CONNECTION');
$db = '获取数据库名称';配置:设置(database.connections.MY_NEW_CONNECTION.database,$ db);DB:setDefaultConnection(“MY_NEW_CONNECTION”);
#5
-3
1) You can define multiple named connections in your database.php config file
1)可以在数据库中定义多个命名连接。php配置文件
'connections' => array(
'tenant1' => array(
...
),
'tenant2' => array(
...
),
Then you can choose which one to use with something like this.
然后你可以选择用哪一个像这样的东西。
$something = DB::connection('tenant1')->select(...);
2) This isn't a full solution as I think it will require some hacking on the core, but you can choose which connection to run a migration on. Maybe you could iterate through your list of tenants and run it on all of them.
2)这不是一个完整的解决方案,因为我认为它需要对内核进行一些修改,但是您可以选择在哪个连接上运行迁移。也许您可以遍历您的租户列表,并在所有租户上运行它。
Schema::connection('tenant1')->create('users', function($table)
3) Unfortunately, I don't think seeding supports multiple connections yet. You might have to roll your own seeding functionality.
不幸的是,我认为播种还不支持多种连接。您可能需要滚动自己的播种功能。