27

目前我有一个托管多个租户的应用程序,这些租户是用 CodeIgniter 编写的。但我真的很喜欢 Laravel 4,我想开始将应用程序迁移到 Laravel。

这是当前的设置:

  • 每个租户都有自己的数据库。
  • 只有一组应用程序文件。
  • 当我们创建一个新租户时,会创建一个新数据库并运行一个安装脚本,并为数据库播种一些初始信息。
  • 每个租户也有自己的子域。这就是我们可以检测使用哪个数据库的方法。
  • 有一个主数据库,其中包含租户信息和用户以及其他一些通用表。
  • 当需要更新架构时,我们只需创建一个将为每个租户运行的更新脚本。这是通过 Codeigniter 的特殊编码 CLI 脚本实现的

在 Codeigniter 中,启动和结束新的数据库连接相对容易。

对于 Laravel,我有以下问题/疑问。

  • 您将如何即时启动/结束数据库连接?
  • 我想使用迁移,但我想为每个租户运行它们。迁移目前仅在“主”数据库连接上运行。它只运行一次。
  • 播种也一样。。

这些是我的主要问题,我还有其他一些小问题,但可以解决。

希望有人可以阐明..

4

5 回答 5

23

我只是对此进行尝试,因此请注意:) 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);
});

就个人而言,我会为每个用户添加一个新方法 User::databaseConnection(),并在我扩展 DatabaseManager 时调用它。

DB::extend($user->username, function() use ($user) {
    return $user->databaseConnection();
});

在整个应用程序中,您应该能够通过以下方式调用注册用户的连接:

DB::connection(Auth::user()->username);

更新

根据您调用租户连接的频率和时间,您可能希望使用 IOC 容器。

App::bind('tenantDB', function()
{
     return DB::connection(Auth::user()->username);
});

App::make('tenantDB')->insert(...);

我忘记了迁移和播种。对于迁移,您可以设置文件路径

php artisan migrate:make foo --path=app/migrations

因此,如果您使用 Config 类来设置默认数据库或 DB::setDefaultConnection($username),我会假设所有迁移和播种都将为当前连接完成。当该过程完成后,您可以切换回主数据库。

更新 2

laravel 开发人员很棒,我绝对应该有冲动去看看这个。您可以在您创建的任何数据库连接上进行迁移和播种。

artisan migrate --database='userConnectionName' 
artisan db:seed --database='userConnectionName'

看看 Barry 的回答,这可能比扩展 DatabaseManager 简单得多。

如果您想查看这些命令的所有选项,只需运行:

artisan help migrate
artisan help db:seed
于 2013-01-25T16:09:58.150 回答
6

您可以使用租户数据库凭据创建 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);

这将需要在您的 database.php 文件中创建 2 个连接。(例如应用程序和租户)并在您的模型中指定要使用的数据库(1 用于存储租户,1 用于租户特定数据库)

并且可能创建一个路由/脚本来创建/更新表。不确定与多个数据库的迁移。

于 2013-01-25T16:46:14.263 回答
4

您可以使用以下语法在 laravel 中创建动态数据库连接

Config::set('database.connections.key', array(
    'driver'    => 'mysql',
    'host'      => 'localhost',
    'database'  => 'dbname',
    'username'  => 'dbuser',
    'password'  => 'dbpass',
    'charset'   => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'prefix'    => '',
));

接着就,随即DB::connection('key'); would just work.

于 2014-01-04T05:31:31.170 回答
0

我最近遇到了类似的问题,不得不为多个模型使用不同的数据库。

我发现以下方法可以解决问题。

  1. 在 app/config/database.php 添加一个新连接 MY_NEW_CONNECTION
  2. 对于新连接,将数据库名称设置为
  3. 在您的 filters.php 或 routes.php 或控制器的 __construct 方法中添加以下内容:

    $db = '获取数据库名称'; Config::set('database.connections.MY_NEW_CONNECTION.database',$db); DB::setDefaultConnection('MY_NEW_CONNECTION');

于 2014-11-13T20:22:09.350 回答
-3

1) 您可以在 database.php 配置文件中定义多个命名连接

'connections' => array(
    'tenant1' => array(
     ...
    ),
    'tenant2' => array(
     ...
    ),

然后你可以选择使用哪一个来处理这样的事情。

$something = DB::connection('tenant1')->select(...);

2)这不是一个完整的解决方案,因为我认为它需要对核心进行一些黑客攻击,但您可以选择在哪个连接上运行迁移。也许您可以遍历您的租户列表并在所有租户上运行它。

Schema::connection('tenant1')->create('users', function($table)

3)不幸的是,我认为播种还不支持多个连接。您可能必须推出自己的播种功能。

于 2013-01-25T15:04:18.440 回答