Laravel 5多租户应用程序具有单独的数据库 - 用户可以访问多个安装

时间:2015-03-09 12:34:59

标签: php laravel laravel-5 multi-tenant

在过去的几年里,我开发了一个非常定制的PHP / MySQL应用程序,用于许多客户端。到目前为止,我一直在为每个客户创建一个新的数据库和新安装。

这里的第一个明显问题是保持多个安装与任何代码更改保持同步;第二个问题是每个安装都有大量用户;对大多数客户而言;其中一些用户是相同的 - 他们必须要记住许多单独的用户帐户和网址。

我现在正在将申请移至Laravel 5,并研究多租户的最佳实施方案;所以寻求关于最佳实施的一点建议。我之前使用过Laravel,但绝不是专家。

就我而言,这就是我所想的。

1个包含表格的主数据库:

  1. 所有用户帐户信息
  2. 访问控制表 - 用户可以访问的安装;他们在该安装上的用户级别是什么。
  3. 每个安装的配置表 - 数据库连接信息,基本配置等。
  4. 然后是每个安装的单独数据库,其中包含该安装所需的所有信息并提交给该安装。

    理想的设置是用户可以转到子域名,即installationname.appname.com;使用他们的主登录详细信息登录并自动进入所需的安装;或者转到appname.com,登录,然后选择要连接的安装。

    我的问题是:

    1. 这是实现我所期待的最佳安排。
    2. 存储用户正在查看的安装(会话变量)
    3. 的最佳方法是什么
    4. 我可以在2个数据库之间定义模型 - 可能将一个连接定义为主连接,然后使用master数据库中的数据库连接信息动态定义另一个连接以连接到正确的安装。 - 系统通常需要检查用户信息的访问级别等。
    5. 我确信有很多我没有想过的问题;但是,如果有人有任何链接或指导,可能有助于这将是伟大的。第一次询问关于SO的问题,但过去在这里找到了大量的研究帮助,感谢社区!


      更新 - 所以我想我现在有办法让这项工作成功;使用上述单独的数据库;设置

      protected $connection = 'tenant_connection'
      

      在与特定于租户的数据库内容相关的模型中。

      然后在头文件中的某个位置根据已在login / by subdomain上设置的会话变量设置所需的tenant_connection。

      $tenant = Installation::where('installation', '=', $session['installation'])->first();
      Config::set('database.connections.tenant_connection', array('driver' => 'mysql', 'host' => $tenant->db_hostname, 'username' => $tenant->db_username)... etc.
      

      假设关系可以跨越连接;我不明白为什么这不起作用;只需要找出最佳位置来设置租户连接。

3 个答案:

答案 0 :(得分:4)

好的,我最终做的是拥有所有用户信息,安装名称和用户可以访问一个数据库中的安装内容的映射,以及单独数据库中的所有租户信息。

然后我有两个连接,mysql和mysql_tenant;其中mysql_tenant数据库不是预先设置的,而是动态的。

User,Installations和mappings模型使用mysql连接,其他所有使用mysql_tenant

为每个安装创建一个代码,并将其用作租户数据库的名称;将此代码存储在会话中。

使用中间件MultiTenant,使用以下关键线控制安装之间的切换:

var data = WhateverYouDoToGetYourData();

var expressions = new OrderExpressions<DemoClass>()
            .Add(x => x.Created, "created")
            .Add(x => x.Approved, "approved")
            .Add(x =>x.Author.Name, "author");

var result = data.OrderBy(expressions, "+created", "-approved", "+author");
// OR
var result = data.OrderBy(expressions, fields);

构建切换等方法还有很多其他内容,但这是要点。

答案 1 :(得分:3)

很难回答您的大部分问题 - 因为它特定于您的申请和意见。

但我能回答的一点是不同的模型可以有不同的数据库连接。因此,您的user模型使用正常的默认连接 - 但您的其他模型可以使用其他连接:

class Example extends Model {

    protected $connection= 'second_db_connection';

}

然后在你的数据库连接文件中 - 你会有这样的东西:

return array(
    'connections' => array(
        'mysql' => array(
            'driver'    => 'mysql',
            'host'      => 'localhost',
            'database'  => 'database1',
            'username'  => 'user1',
            'password'  => 'pass1'
            'charset'   => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix'    => '',
        ),

        'second_db_connection' => array(
            'driver'    => 'mysql',
            'host'      => 'localhost',
            'database'  => 'database2',
            'username'  => 'user2',
            'password'  => 'pass2'
            'charset'   => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix'    => '',
        ),
    ),

答案 2 :(得分:0)

Laravel 5已经足够先进,您应该只需要一个安装以及一个战略数据库,并且具有良好定义的关系和密钥。几乎不需要多个数据库。

如果您可以更具体地了解您的要求,我可以提供更具体的答案。