Laravel 4:多租户应用,每个租户都有自己的数据库和一个全局数据库
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14524181/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Laravel 4: Multiple Tenant Application, each tenant it's own database and one global database
提问by Victor Gutierrez
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.
对于 Laravel,我有以下问题/疑问。
- 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..
希望有人能阐明一些..
采纳答案by Blessing
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 时都会使用它,具有和扩展方法。这是源的链接。DB::connection() 方法应该返回一个Illuminate\Database\Connection的实例。根据所有这些,我将创建一个新的用户连接,如下所示:
$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.
因此,如果您使用 Config 类来设置默认数据库或 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
回答by Barryvdh
You can create 1 database with the tenant database credentials, and dynamically set them in your app:
您可以使用租户数据库凭据创建 1 个数据库,并在您的应用程序中动态设置它们:
$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)
这将需要在您的 database.php 文件中创建 2 个连接。(例如应用程序和租户)并在您的模型中指定要使用的数据库(1 用于存储租户,1 用于租户特定数据库)
And probably create a route/script to create/update the tables. Not sure about migrations with multiple databases.
并且可能创建一个路由/脚本来创建/更新表。不确定与多个数据库的迁移。
回答by Harish Anchu
You can create dynamic DB connections in laravel with following syntax
您可以使用以下语法在 laravel 中创建动态数据库连接
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::connection('key'); would just work.
回答by michaeltintiuc
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
- 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:
$db = 'get your database name'; Config::set('database.connections.MY_NEW_CONNECTION.database',$db); DB::setDefaultConnection('MY_NEW_CONNECTION');
- 在 app/config/database.php 添加一个新的连接 MY_NEW_CONNECTION
- 对于新连接,将数据库名称设置为任何
在您的 filters.php 或 routes.php 或控制器的 __construct 方法中添加以下内容:
$db = '获取你的数据库名称'; 配置::设置('database.connections.MY_NEW_CONNECTION.database',$db); DB::setDefaultConnection('MY_NEW_CONNECTION');
回答by Anand Capur
1) You can define multiple named connections in your database.php config file
1) 您可以在 database.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.
3)不幸的是,我认为播种尚不支持多个连接。您可能需要推出自己的播种功能。