Yii2 多租户架构 - 选择正确的数据库
Yii2 Multi-Tenant Architecture - Choose correct database
我正在使用 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 文件中第一个声明的数据库中获取角色。因此,无论登录用户是什么,都会使用第一个数据库。
问题:
- 我该如何解决这个问题?您是否知道将角色授予登录用户的文件在哪里?
- 奖金问题:你认为这个策略是错误的吗?如果是这样,你有什么建议?
非常感谢您的宝贵时间和支持。
这是关于 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>'
]
编辑:重读您的 post 之后...每个用户都不需要自己的 rbac table/schema。使用 Yii 现有的系统。
问题#1:我该如何解决这个问题?您是否知道将角色授予登录用户的文件在哪里?
I would suggest you use yii2 admin extension for this purpose(https://github.com/mdmsoft/yii2-admin) that will solve your issue and it is the best extension to manage user role. use this link for better understanding (https://github.com/mdmsoft/yii2-admin/blob/master/docs/guide/configuration.md)
- 按照上面的 URL 进行安装,或者只需在 composer.json 文件中添加 "mdmsoft/yii2-admin": "~2.0" 和 运行 作曲家更新.
成功安装此扩展后运行迁移创建RBAC tables,如果您已经安装则跳过它。
yii migrate --migrationPath=@yii/rbac/migrations
你必须在你的 main.php 中做一些配置来告诉你的应用程序关于 public 路由和所有其他应用程序路由系统将在它们上实施 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',
]
]
以上设置将告诉您的应用程序进行登录、注销、错误和索引功能 public 在站点控制器下,所有其他应用程序路由需要分配 RBAC 才能执行操作.
main.php存在于backend/config/main。php在我的例子中,你可以根据你的要求使用可能在 common/config/main.php
问题 #2: 奖励问题:你认为这个策略是错误的吗?如果是这样,你有什么建议?
我认为您的方法不可扩展,我建议您创建一个主数据库并将其用于您的应用程序租户及其数据库。
- 在 master 数据库中使用租户名称设置租户 table,数据库需要参数
在您的应用程序中建立主数据库连接,用于获取所有租户并存储来自主数据库的数据库连接。
'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);
``
获得租户信息后,您可以从 master 数据库中获取租户并将其数据库设置添加到 SESSION 中。
创建一个 BaseModel.php class 并使用您所有的应用程序模型扩展它 classes.
- 在你BaseModel.php中添加下面的方法来建立运行time DB连接基于从登录页面选择域或租户。
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;
}
}
- 通过这样做,您可以选择从后端向主数据库添加多个租户,这将自动在您的应用程序中可用。
我相信这些信息对您有帮助。
干杯!!!
我正在使用 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 文件中第一个声明的数据库中获取角色。因此,无论登录用户是什么,都会使用第一个数据库。
问题:
- 我该如何解决这个问题?您是否知道将角色授予登录用户的文件在哪里?
- 奖金问题:你认为这个策略是错误的吗?如果是这样,你有什么建议?
非常感谢您的宝贵时间和支持。
这是关于 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>'
]
编辑:重读您的 post 之后...每个用户都不需要自己的 rbac table/schema。使用 Yii 现有的系统。
问题#1:我该如何解决这个问题?您是否知道将角色授予登录用户的文件在哪里?
I would suggest you use yii2 admin extension for this purpose(https://github.com/mdmsoft/yii2-admin) that will solve your issue and it is the best extension to manage user role. use this link for better understanding (https://github.com/mdmsoft/yii2-admin/blob/master/docs/guide/configuration.md)
- 按照上面的 URL 进行安装,或者只需在 composer.json 文件中添加 "mdmsoft/yii2-admin": "~2.0" 和 运行 作曲家更新.
成功安装此扩展后运行迁移创建RBAC tables,如果您已经安装则跳过它。
yii migrate --migrationPath=@yii/rbac/migrations
你必须在你的 main.php 中做一些配置来告诉你的应用程序关于 public 路由和所有其他应用程序路由系统将在它们上实施 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', ] ]
以上设置将告诉您的应用程序进行登录、注销、错误和索引功能 public 在站点控制器下,所有其他应用程序路由需要分配 RBAC 才能执行操作.
main.php存在于backend/config/main。php在我的例子中,你可以根据你的要求使用可能在 common/config/main.php
问题 #2: 奖励问题:你认为这个策略是错误的吗?如果是这样,你有什么建议?
我认为您的方法不可扩展,我建议您创建一个主数据库并将其用于您的应用程序租户及其数据库。
- 在 master 数据库中使用租户名称设置租户 table,数据库需要参数
在您的应用程序中建立主数据库连接,用于获取所有租户并存储来自主数据库的数据库连接。
'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);
``
获得租户信息后,您可以从 master 数据库中获取租户并将其数据库设置添加到 SESSION 中。
创建一个 BaseModel.php class 并使用您所有的应用程序模型扩展它 classes.
- 在你BaseModel.php中添加下面的方法来建立运行time DB连接基于从登录页面选择域或租户。
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;
}
}
- 通过这样做,您可以选择从后端向主数据库添加多个租户,这将自动在您的应用程序中可用。
我相信这些信息对您有帮助。
干杯!!!