我正在尝试使用Laravel 5进行构建和应用。它应该是一个使用多个数据库的多租户数据库架构。出于安全考虑,我的雇主要求这样做。
我尝试过手动管理主数据库迁移和租户迁移但失败了。所以我决定接受Laravel特定包的帮助,这应该是我需要的。
Tenanti提供了解决我的目的的方法,但问题是我是一名新手开发人员,我无法完全理解如何在我的应用程序中使用它。
我已正确安装,我相信:
composer require "orchestra/tenanti=~3.0"
在配置应用文件中添加这些提供者和别名:
'providers' => [
// ...
Orchestra\Tenanti\TenantiServiceProvider::class,
Orchestra\Tenanti\CommandServiceProvider::class,
],
'aliases' => [
'Tenanti' => Orchestra\Support\Facades\Tenanti::class,
],
最后发布配置并根据多个数据库的文档进行调整:
php artisan vendor:publish
return [
'drivers' => [
'user' => [
'model' => App\User::class,
'migration' => 'tenant_migrations',
'path' => database_path('tenanti/user'),
],
],
];
此时我还在模糊下一步做什么?
我的怀疑如下:
我尝试运行一些附带的工匠命令,如:
php artisan tenanti:install {driver}
php artisan tenanti:make {driver} {name}
但我收到的错误是这样的:
[InvalidArgumentException]数据库连接 [租户]不可用。
我在哪里可以找到资源来了解如何继续进行此操作?
答案 0 :(得分:11)
+1给@morphatic答案,它对大多数东西都很安静。
一组文件用于主DB,它将存储所有租户信息,其他文件用于租户DB。那么这些存储的方式和位置呢?
对于您的主数据库,您应该能够使用默认database/migration
并使用php artisan make:migration
和php artisan migrate
。
'path' => database_path('tenanti/user'),
在这种情况下,将从database/tenanti/user
创建/迁移迁移(您可以选择其他文件夹,它将使用该文件夹)。设置完成后,您可以通过php artisan tenanti:make user create_blogs_table
(作为示例)为用户租户创建新的迁移文件,并通过php artisan tenanti:migrate user
运行迁移(请参阅Laravel迁移命令与Tenanti之间的相似性?)。
驱动程序只是租户的分组,您可以按用户,公司或团队等对其进行分组。每个项目可能需要多个类型的组,否则大多数时候您只需要使用单个"组"或"司机"。
我如何处理应用程序的身份验证?我的意思是每当租户登录时,我都必须确保与数据库的连接动态变化。我将如何实现这一目标?
首先,您需要考虑如何计划区分每个租户。大多数时候我会看到人们倾向于选择子域名。因此,在这种情况下,您需要使用中间件检查子域是否属于任何用户(通过查询主数据库),然后连接到属于该用户的数据库。
Tenanti并不管理流程的这一部分,因为每个人在这方面都有不同的风格,但我们提供了一个代码,可以从基础数据库配置动态连接到数据库租户。假设你有以下配置:
<?php
return [
'fetch' => PDO::FETCH_CLASS,
'default' => 'primary',
'connections' => [
'primary' => [
//
],
'tenants' => [
'driver' => 'mysql',
'host' => 'dbhost', // for user with id=1
'username' => 'dbusername', // for user with id=1
'password' => 'dbpassword', // for user with id=1
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
],
],
'migrations' => 'migrations',
'redis' => [ ... ],
];
您可以按照https://github.com/orchestral/tenanti#multi-database-connection-setup中提供的步骤操作,并添加以下代码。
<?php namespace App\Providers;
use Orchestra\Support\Facades\Tenanti;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
Tenanti::setupMultiDatabase('tenants', function (User $entity, array $template) {
$template['database'] = "tenant_{$entity->getKey()}";
return $template;
});
}
}
这将确保您为user = 1使用tenant_1
数据库,为user = 2使用tenant_2
数据库,依此类推。
这是您需要在中间件中添加逻辑的地方。
$user = App\User::whereSubdomain($request->route()->parameter('tenant'))->first();
Tenanti::driver('user')->asDefaultDatabase($user, 'tenants_{id}');
答案 1 :(得分:5)
我从来没有使用过这个软件包,但是使用上面提到的代码,我认为可能接近正确的解决方案。您可能仍需要使用其中一些值来纠正它们:
由于您使用的是多数据库配置,我相信您应该能够将迁移保留在正常位置,即database/migrations
。然后,Tenanti
将为不同数据库中的每个租户创建数据库的精确副本。但是,当您运行php artisan tenanti:install user
时,它实际上可能会在database/
下创建一个文件夹,指示您应该将迁移放在何处。
driver
描述Tenanti
是使用单个还是多个数据库,使用哪些模型来确定不同的租户,以及存储迁移的位置。这是您在上面使用的Tenanti
配置文件中标识的内容。
您需要按如下方式更新config/database.php
。在普通 Laravel
应用中,您可以按如下方式设置数据库连接:
<?php
return [
'fetch' => PDO::FETCH_CLASS,
'default' => env('DB_CONNECTION', 'mysql'),
'connections' => [
'sqlite' => [ ...DB connection info... ],
'mysql' => [ ...DB connection info... ],
'pgsql' => [ ...DB connection info... ],
'sqlsrv' => [ ...DB connection info... ],
],
'migrations' => 'migrations',
'redis' => [ ... ],
];
但是,在Tenanti
多数据库设置的情况下,您需要为每个租户的数据库添加不同的连接信息。为此,您需要为database.php
配置文件添加一个新级别(此示例假设您使用的是mysql,但您可以使用任何数据库,甚至不同的租户使用不同的数据库引擎):
<?php
return [
'fetch' => PDO::FETCH_CLASS,
'default' => env('DB_CONNECTION', 'mysql'),
'connections' => [
'tenants' => [
'user_1' => [
'driver' => 'mysql',
'host' => 'dbhost', // for user with id=1
'database' => 'dbname', // for user with id=1
'username' => 'dbusername', // for user with id=1
'password' => 'dbpassword', // for user with id=1
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
'user_2' => [
'driver' => 'mysql',
'host' => 'dbhost', // for user with id=2
'database' => 'dbname', // for user with id=2
'username' => 'dbusername', // for user with id=2
'password' => 'dbpassword', // for user with id=2
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
],
],
'migrations' => 'migrations',
'redis' => [ ... ],
];
如您所见,每个租户都有自己的数据库实例,可以位于不同的主机上,并具有不同的用户名/密码。需要告诉Tenanti
如何确定要使用的数据库。这是the documentation on Database Connection Resolver描述的内容。在他们的示例中,他们使用acme_{$user->id}
命名了他们的租户数据库,而在上面的示例中,我使用了user_{$user->id}
。
就像我说的那样,我从来没有真正自己设置过,但这些是基于文档的最佳猜测,并且使用了同一个开发人员的其他软件包。希望这有帮助!