我正在使用SLIM编写一个API
,该API的目标是创建一个多租户结构。到目前为止,我所做的是:
首先,我创建了一个 master 数据库,其中包含我的所有客户(购买了我的软件),对于每个客户,我都有一个名为CUSTOMER_TOKEN
的字段,该字段代表凭据来访问API。
基本上,我在这里有两个软件:
事实上,每个租户都有一个不同的数据库,我发现这种方式对我来说是最佳选择。
主应用程序获得JWT
令牌,方法是使用API
向CUSTOMER_TOKEN
发送请求,例如:
http://xxx.xxx.xxx.xxx/v1/auth/login
上述路线将在 master 数据库中检查客户的存在(如果存在),然后将返回临时访问令牌以使用API
(JWT)。
到目前为止一切都很好。主要问题来了。实际上,如果用户拥有JWT
并且CUSTOMER_TOKEN
有效,则API
应该创建与tenant
数据库的连接,而不是 master < / strong>数据库。
此刻,为了处理主连接,我特别使用了SLIM
容器:
<?php
use Slim\Container;
$container = $app->getContainer();
$container['pdo'] = function (Container $c) {
$db = $c['settings']['db'];
$pdo = new PDO(
"mysql:host=" . $db['host'] . ";dbname=" . $db['dbname'],
$db['user'],
$db['pass']
);
return $pdo;
};
如何从此处创建与租户数据库的不同连接?我应该使用middleware
吗?我应该检查请求的路由器以了解是否需要主数据库或租户数据库吗?
请注意,对于每个租户,我使用一个名称约定结构,例如:
app_name-tenant-tenant_name
因此,我的前缀为app_name-tenant
,然后是tenant_name
。因此,我只需要从 master 数据库获取customer
的名称即可组装连接。
您将如何处理这种情况?谢谢。
答案 0 :(得分:1)
出于安全和实际原因,我建议使用两个不同的PDO连接(实例)。第一个连接用于API(JWT)Auth,第二个数据库连接用于客户(租户)。您不需要中间件,因为基础结构配置中的数据库连接部分位于中间件下方。
您有多个选项可以与容器结合使用来管理数据库连接。
pdo2
或db2
或对您有意义的类似物。// API
$container['pdo'] = function (Container $container) {
// Customer database
$container['pdo2'] = function (Container $container) {
示例:
class ApiDatabase extends PDO {}
$container[ApiDatabase::class] = function (Container $container) {
class CustomerDatabase extends PDO {}
$container[CustomerDatabase::class] = function (Container $container) {
名称约定
现在,您已经为客户建立了第二个数据库连接,不再需要表前缀,因为在技术上客户之间已经有了更好的分隔。为什么?数据库事务也完全分开,这对其他客户数据(和表)没有影响。数据库迁移将更加容易,因为您不必担心前缀。现在,您可以为每个客户部署新版本,而不会影响其他客户的数据库。