简体   繁体   English

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

[英]Laravel 5 Multi-Tenancy App with separate databases - users have access to multiple installations

Over the past couple of years I have developed a very customised PHP/MySQL application that is used for a number of clients. 在过去的几年里,我开发了一个非常定制的PHP / MySQL应用程序,用于许多客户端。 I have been creating a new database and new installation for each client up to this point. 到目前为止,我一直在为每个客户创建一个新数据库和新安装。

The first obvious problem here is keeping multiple installations up to date with any code changes; 这里的第一个明显问题是保持多个安装与任何代码更改保持同步; a second problem is that each installation has a large amount of users; 第二个问题是每个安装都有大量用户; and for most clients; 对大多数客户而言; some of these users are the same - and they have to have a number of seperate user accounts and urls to remember. 其中一些用户是相同的 - 他们必须要记住许多单独的用户帐户和网址。

I am moving the application over to Laravel 5 at the moment and looking into the best implementation for multi-tenancy; 我现在正在将申请移至Laravel 5,并研究多租户的最佳实施方案; so looking for a little advice on the best implementation. 所以寻求关于最佳实施的一点建议。 I've used Laravel before but am by no means an expert. 我之前使用过Laravel,但绝不是专家。

This is what I am thinking as far as setup. 就设置而言,这就是我的想法。

1 Master Database that holds tables for: 1个主数据库,用于保存表:

  1. All User account information 所有用户帐户信息
  2. Access Control Table - which installations the users can access; 访问控制表 - 用户可以访问的安装; what their user level on that installation is. 他们在该安装上的用户级别是什么。
  3. Configuration table for each installation - database connection info, basic configuration etc. 每个安装的配置表 - 数据库连接信息,基本配置等。

Then a seperate database for each installation that contains all the information that is needed for, and submitted to, that installation. 然后是每个安装的单独数据库,其中包含该安装所需的所有信息以及提交给该安装的所有信息。

The ideal setup is that a user can go to a subdomain ie installationname.appname.com; 理想的设置是用户可以转到子域,即installationname.appname.com; sign in with their master login details and automatically go to the required installation; 使用他们的主登录详细信息登录并自动进入所需的安装; OR go to appname.com, sign in and then select which installation to connect to. 或者转到appname.com,登录,然后选择要连接的安装。

My questions are: 我的问题是:

  1. Is this the best arrangement to achieve what I am looking for. 这是实现我所期待的最佳安排吗?
  2. What's the best method for storing which installation the user is looking at (session variable) 存储用户正在查看的安装的最佳方法是什么(会话变量)
  3. Can I define a model between 2 databases - perhaps define one connection as master connection, then dynamically define another connection using the database connection information in the master database to connect to the correct installation. 我可以在两个数据库之间定义模型 - 可能将一个连接定义为主连接,然后使用master数据库中的数据库连接信息动态定义另一个连接以连接到正确的安装。 - the system will often need to check the user info for access level etc. - 系统通常需要检查用户信息的访问级别等。

I'm sure there's a lot of issues that I have not thought of; 我确信有很多我没有想过的问题; but if anyone has any links or guidance that may help that would be great. 但是,如果有人有任何链接或指导,可能有助于这将是伟大的。 First time asking a question on SO but have found a huge amount of research help here in the past so thanks to the community! 第一次询问关于SO的问题,但过去在这里找到了大量的研究帮助,感谢社区!


UPDATE - So I think I have a way to make this work now; 更新 - 所以我想我现在有办法让这项工作; using seperate databases as above; 使用上述单独的数据库; set

protected $connection = 'tenant_connection'

in the models relating to tenant-specific database content. 在与租户特定的数据库内容相关的模型中。

Then somewhere in a header file set the tenant_connection that is wanted based on a session variable which has been set on login/by subdomain. 然后在头文件中的某个位置根据已在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.

Assuming relationships will work across connections; 假设关系可以跨越连接; I don't see why this would not work; 我不明白为什么这不起作用; just need to work out best place to set the tenant connection. 只需要找出最佳位置来设置租户连接。

Ok so what I ended up doing was having all user info, names of installations and mappings of what users can access what installations in one database, and all tenant info in seperate databases. 好的,我最终做的是拥有所有用户信息,安装名称和用户可以访问一个数据库中的安装内容的映射,以及单独数据库中的所有租户信息。

I then had two connections, mysql and mysql_tenant; 然后我有两个连接,mysql和mysql_tenant; where mysql_tenant database is not pre-set but dynamic. 其中mysql_tenant数据库不是预先设置的,而是动态的。

The User, Installations and mappings model use the mysql connection, all others use mysql_tenant User,Installations和mappings模型使用mysql连接,其他所有使用mysql_tenant

Created a code for each installation, and used this as the name of the tenant database; 为每个安装创建一个代码,并将其用作租户数据库的名称; storing this code in the session. 将此代码存储在会话中。

Used a middleware MultiTenant, to control the switching between installations using these key lines: 使用中间件MultiTenant,使用以下关键线控制安装之间的切换:

$tenant_id = session()->get('tenant');

\Config::set('database.connections.mysql_tenant.database', $dbname);
\DB::setDefaultConnection('mysql_tenant');

There's a lot more to it for building the method to switch etc, but this is the gist. 构建切换方法等等还有很多,但这是要点。

It is difficult to answer most of your question - as it is specific to your application and opinion based. 很难回答大部分问题 - 因为它特定于您的申请和基于意见。

But the one bit I can answer is different models can have different database connections. 但我能回答的一点是不同的模型可以有不同的数据库连接。 So your user model uses the normal default connection - but your other models can use another connection: 因此,您的user模型使用普通的默认连接 - 但您的其他模型可以使用其他连接:

class Example extends Model {

    protected $connection= 'second_db_connection';

}

Then in your DB connection file - you would have something like this: 然后在你的数据库连接文件中 - 你会有这样的东西:

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'    => '',
        ),
    ),

Laravel 5 is advanced enough that you should be able to have simply one installation along with a strategic database, with well defined relations and keys. Laravel 5已经足够先进,您应该只需要一个安装以及一个战略数据库,并且具有良好定义的关系和密钥。 There is rarely ever a need for multiple databases. 几乎不需要多个数据库。

If you can be more specific about your requirements I can provide a more specific answer. 如果您可以更具体地了解您的要求,我可以提供更具体的答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM