【问题标题】:Yii2 Multi-Tenant Architecture - Choose correct databaseYii2 多租户架构 - 选择正确的数据库
【发布时间】:2016-12-22 14:53:50
【问题描述】:

我正在使用 Yii2 构建应用程序,并且正在使用多租户架构。所以......每个客户都有自己的数据库(相同的结构)。

到目前为止我做了什么:

  • 我在 config/web.php 文件中声明了所有不同的数据库
  • 我有一个主数据库,将每个用户对应到他的数据库。因此,当有人登录时,应用知道应该使用哪个数据库。

我做了什么但我不确定:

我用以下代码创建了一个文件 components/ActiveRecord.php:

<?php
namespace app\components;
use Yii;

class ActiveRecord extends \yii\db\ActiveRecord {

    public static function getDb() {
        if (isset($_SESSION['userdb'])) {
            $currentDB = $_SESSION['userdb'];
            return Yii::$app->get($currentDB);
        }
    }

}?>

所以...登录时,我将数据库保存在会话中,并在上述扩展默认 ActiveRecord 的文件中,我覆盖了 getDb 函数并选择了我自己的。随后,我更改了所有模型,以便它们扩展我的 ActiveRecord。

我不确定这个策略是否正确,但它几乎可以工作。

问题出在哪里:

除了... RBAC,一切正常!对于 RBAC,我使用 yii2-rbac 扩展。问题是用户不是从他的数据库中获取他的角色,而是从 config/web.php 文件中第一个声明的数据库中获取他的角色。因此,无论登录用户如何,都会使用第一个数据库。

问题:

  1. 我该如何解决这个问题?您知道将角色授予登录用户的文件在哪里吗?
  2. 额外问题:您认为这种策略是错误的吗?如果是这样,您有什么建议?

非常感谢您的宝贵时间和支持。

【问题讨论】:

    标签: yii2 multi-tenant


    【解决方案1】:

    问题#1:我该如何解决这个问题?您知道将角色授予登录用户的文件在哪里吗?

    我建议您为此目的使用 yii2 管理员扩展 (https://github.com/mdmsoft/yii2-admin),这将解决您的问题,它是管理用户角色的最佳扩展。使用此链接更好地理解 (https://github.com/mdmsoft/yii2-admin/blob/master/docs/guide/configuration.md)

    • 按照上面的 URL 进行安装,或者在您的 composer.json 文件中添加 "mdmsoft/yii2-admin": "~2.0" 并运行 composer update
    • 成功安装此扩展后,运行迁移以创建 RBAC 表,如果您已经跳过它。 yii migrate --migrationPath=@yii/rbac/migrations

    • 您必须在 main.php 中进行一些配置,以告知您的应用程序有关公共路由的信息,并且所有其他应用程序路由系统将在它们上实施 RBAC。

    • 这是您必须在 main.php 文件中添加的内容。

      'components' => [], 'as access' => [ 'class' => 'mdm\admin\components\AccessControl', 'allowActions' => [ 'site/login', // add or remove allowed actions to this list 'site/logout', 'site/error', 'site/index', ] ]

    • 以上设置将告诉您的应用程序使登录、注销、错误和索引功能在站点控制器下是公开的,并且所有其他应用程序路由都需要分配 RBAC 才能执行该操作。

    • ma​​in.php在我的例子中存在于backend/config/main.php,你可以根据你的要求使用common/config/main.php

    问题 #2: 额外问题:您认为这种策略是错误的吗?如果是这样,您有什么建议?

    我认为您的方法不可扩展,我建议您创建一个主数据库并将其用于您的应用程序租户及其数据库。

    • 在主数据库中使用租户名称、数据库所需参数设置租户表
    • 在您的应用程序中建立主数据库连接,用于获取所有租户并存储来自主数据库的数据库连接。

      'db' => [ 'class' => 'yii\db\Connection', 'dsn' => 'mysql:host=127.0.0.1;dbname=master-db', 'username' => 'root', 'password' => 'root', 'charset' => 'utf8', ]

    • 现在在登录页面显示租户列表以选择他们的信息如果您为每个租户使用唯一域,您也可以使用域名。如果您使用的是唯一域,那么您必须将带有租户信息的域名存储在主数据库中,以便能够根据域获取租户信息。

    // 在成功登录页面设置会话值读取用户域并从主数据库获取租户信息并添加到会话中。

    ``
      $tenant = Tenant::findOne(Yii::$app->request->post('tenant_id'));
      Yii::$app->session->set('DB_HOST', $tenant->DB_host);
      Yii::$app->session->set('DB_USER', $tenant->DB_username);
      Yii::$app->session->set('DB_PASS', $tenant->DB_password);
      Yii::$app->session->set('DB_NAME', $tenant->DB_name);
    ``
    
    • 获得租户信息后,您可以从主数据库中获取租户并将其数据库设置添加到 SESSION。

    • 创建一个 BaseModel.php 类并使用所有应用程序模型类对其进行扩展。

    • 在您BaseModel.php中添加以下方法,以根据登录页面中的域或租户选择进行运行时数据库连接。

    public static function getDb(){ if ( Yii::$app->session->get('DB_HOST') ){ $host = Yii::$app->session->get('DB_HOST'); $dbName = Yii::$app->session->get('DB_NAME'); $dsn = "mysql:host=$host;dbname=$dbName"; Yii::$app->db->dsn = $dsn; Yii::$app->db->username = Yii::$app->session->get('DB_USER'); Yii::$app->db->password = Yii::$app->session->get('DB_PASS'); return Yii::$app->db; } }

    • 通过这样做,您可以选择将多个租户从后端添加到主数据库,这将自动在您的应用程序中可用。

    我相信这些信息对您有所帮助。

    干杯!!!

    【讨论】:

    • 感谢 user3083356。你的回复很有用。我只有一个问题。我通过扩展 ActiveController 而不是 BaseModel 来做类似的事情。你认为这不正确吗?
    【解决方案2】:

    这是dbmanager 上的文档。

    如果您想从其他数据库获取 rbac 信息,这应该可以。

    在您的配置文件夹中,创建一个名为 rbacdb.php 的文件。添加以下内容:

    <?php
    
    return [
    'class' => 'yii\db\Connection',
    'dsn' => 'mysql:host=<db host or ip>;dbname=<dbname>',
    'username' => '<dbuser>',
    'password' => '<dbPassword>',
    'charset' => 'utf8',
    ];
    

    然后转到您的配置文件并找到 authmanger 部分。它应该是这样的:

    'authManager' => [
    'class' => 'yii\rbac\DbManager',
    'db'=> require(__DIR__ . '/rbacdb.php'),
    'assignmentTable'=>'<tableName>',
    'itemChildTable'=>'<tableName>',
    'itemTable'=>'<tableName>',
    'ruleTable'=>'<tableName>'
    ]
    

    编辑:重读您的帖子后……每个用户都不需要自己的 rbac 表/模式。使用 Yii 现有的系统。

    【讨论】:

    猜你喜欢
    • 2013-12-26
    • 1970-01-01
    • 2012-07-18
    • 1970-01-01
    • 2015-01-05
    • 2017-12-16
    • 1970-01-01
    • 2011-05-25
    • 2023-01-28
    相关资源
    最近更新 更多