elimuswift/connection-resolver

一个Laravel包,能够动态地在不同的数据库连接之间切换

v1.0.3 2017-03-20 07:46 UTC

This package is auto-updated.

Last update: 2024-09-14 17:37:25 UTC


README

Packagist License Latest Stable Version Total Downloads Build Status

Laravel Tenantable包旨在在不访问数据库 ::connection('name') 的每个数据库调用的情况下,动态地启用基于数据库连接的多租户。

安装

只需通过composer.json将新包添加到您的Laravel安装中

composer require leemason/tenantable

然后运行composer dump-autoload

更新composer后,将ServiceProvider添加到config/app.php中的providers数组。理想情况下,您应该将其插入到Illuminate\Database\DatabaseServiceProvider::class之后,以确保其boot方法在数据库可用但在其他Service Providers启动之前被调用。

Laravel 5.1

LeeMason\Tenantable\TenantableServiceProvider::class,

运行迁移

artisan migrate --path /vendor/leemason/tenantable/migrations

然后在您的流程中创建Eloquent方式租户

$tenant = new \LeeMason\Tenantable\Tenant();
$tenant->domain = 'domain.com';
$tenant->driver = 'mysql';
$tenant->host = 'localhost';
$tenant->database = 'domain_com';
$tenant->username = 'root';
$tenant->password = '';
$tenant->prefix = 'prefix';
$tenant->save();

就这样!每当您的应用通过 http://domain.com 访问时,默认数据库连接将设置为上述详细信息。

兼容性

Tenantable包是在Laravel 5.1上开发的,我看不出为什么它不能与5.0兼容,但它只测试了5.1及以上版本。

简介

该包通过连接数据库中保存的连接详细信息,通过访问的域名简单地解析正确的连接详细信息。

一旦解析,它就使用保存的值设置默认数据库连接。

这避免了根据访问的租户切换或以编程方式访问正确连接的需要。

这意味着所有您的路由、模型等都将运行在活动租户数据库上(除非明确通过::connection('name')指定)。

生命周期

这是在HTTP请求期间的工作方式

  • Tenantable将默认数据库连接的名称复制到tenantable.database.default配置区域。
  • Tenantable通过Http\Request::getHost()方法获取主机字符串。
  • Tenantable在数据库中查找与该主机匹配的租户。
  • 如果没有找到,Tenantable在Domains表中查找匹配项(如果找到,则使用Eloquent关系返回Tenant模型)。
  • 找到匹配项后,将其保存为活动租户,并将租户的数据库详细信息放入database.connections.tenant配置。
  • 然后将默认数据库连接更改为'tenant'并清除连接(断开/重新连接)。
  • app.url配置设置为租户域名。
  • 如果在任一表中找不到匹配项,将触发TenantNotResolved事件,不会发生配置更改。

这是在Artisan控制台请求期间的工作方式

  • Tenantable将默认数据库连接的名称复制到tenantable.database.default配置区域。
  • Tenantable注册了一个控制台选项--tenant,您可以在其中提供id、uuid、域名或*,all以运行所有租户。
  • Tenantable检查是否提供了租户选项,如果没有提供,则不解析租户。命令正常运行。
  • 如果找到匹配项,它将解析租户(设置租户连接详细信息)然后再执行命令。
  • 如果您通过--tenant提供*或字符串all,Tenantable将为数据库中找到的每个租户运行命令,在每次运行之前设置活动租户。

解析器类

负责在http和console访问期间解析和管理活动租户的\LeeMason\Tenantable\Resolver类。

TenantableServiceProvider将此类注册为单例,以便在您的应用中的任何地方通过方法注入或使用app('LeeMason\Tenantable\Resolver')辅助函数使用。

该类为您提供了访问或修改活动租户的方法。

//fetch the resolver class either via the app() function or by injecting
$resolver = app('LeeMason\Tenantable\Resolver');

//check if a tenant was resolved
$resolver->isResolved(); // returns bool

//get the active tenant model
$tenant = $resolver->getActiveTenant(); // returns instance of \LeeMason\Tenantable\Tenant or null

//set the active tenant
$resolver->setActiveTenant(\LeeMason\Tenantable\Tenant $tenant); // fires a \LeeMason\Tenantable\Events\SetActiveTenantEvent event

//purge tenant connection
$resolver->purgeTenantConnection();

//reconnect tenant connection
$resolver->reconnectTenantConnection();

租户模型

\LeeMason\Tenantable\Tenant 类是一个非常简单的 Eloquent 模型,具有一些数据库连接属性,并且当访问时,元属性会被转换为一个 Illuminate\Support\Collection

每个属性(除了 id、uuid、domain、driver、prefix、meta 和时间戳)都进行了加密以确保安全,访问时解密,保存时自动加密。

每个模型实例在创建时都会分配一个 uuid,该属性不能设置/更改,因为它是为该租户生成的唯一标识符。

使用 uuid 的原因是为了允许您在其他地方使用租户的标识符而不暴露租户的 id 或域名(例如在文件系统中,您可以在子文件夹中存储特定于租户的文件)。

该模型可以像其他 Eloquent 模型一样用于创建/读取/更新/删除。

//create by mass assignment
\LeeMason\Tenantable\Tenant::create([
    'domain' => 'http://...'
    ....
]);

//call then save
$tenant = \LeeMason\Tenantable\Tenant();
$tenant->domain = 'http://...';
...
$tenant->save();

//fetch all tenants
$tenant = \LeeMason\Tenantable\Tenant::all();

//fetch by domain
$tenant = \LeeMason\Tenantable\Tenant::where('domain', 'http://..')->first();

事件

Tenantable 包生成了一些事件,您可以在应用程序中消费这些事件。

\LeeMason\Tenantable\Events\SetActiveTenantEvent(\LeeMason\Tenantable\Tenant $tenant)

当设置租户为活动租户时,将触发此事件,并且有一个公共的 $tenant 属性,其中包含 \LeeMason\Tenantable\Tenant 实例。

注意 这可能不是由解析器触发的结果,也可能是在以编程方式设置租户为活动租户时触发的。

\LeeMason\Tenantable\Events\TenantResolvedEvent(\LeeMason\Tenantable\Tenant $tenant)

当解析器解析租户时,将触发此事件,并且有一个公共的 $tenant 属性,其中包含 \LeeMason\Tenantable\Tenant 实例。

注意 由于解析器负责此事件,因此此事件在每个请求中仅触发一次。

\LeeMason\Tenantable\Events\TenantNotResolvedEvent(\LeeMason\Tenantable\Resolver $resolver)

当解析器无法解析租户时,将触发此事件,并且有一个公共的 $resolver 属性,其中包含 \LeeMason\Tenantable\Resolver 实例。

注意 由于解析器负责此事件,因此此事件在每个请求中仅触发一次。

关于使用 Artisan::call(); 的说明

使用 Artisan Facade 运行命令时,无法在运行之前更改应用程序的活动租户(与控制台 artisan 访问不同)。

因此,将使用当前活动租户。

要为每个租户运行命令,您需要使用 Tenant::all() 获取所有租户,并在设置活动租户后,在 foreach 循环内部运行 Artisan::call() 方法,如下所示

//fetch the resolver class either via the app() function or by injecting
$resolver = app('LeeMason\Tenantable\Resolver');

//store the current tenant
$resolvedTenant = $resolver->getActiveTenant();

//fetch all tenants and loop / call command for each
$tenants = \LeeMason\Tenantable\Tenant::all();
foreach($tenants as $tenant){
    $resolver->setActiveTenant($tenant);
    $result = \Artisan::call('commandname', ['array' => 'of', 'the' => 'arguments']);
}

//restore the correct tenant
$resolver->setActiveTenant($resolvedTenant);

如果您需要在原始默认连接(即不是租户连接)上运行 Artisan Facade,请首先调用 Resolver::purgeTenantConnection() 函数

//fetch the resolver class either via the app() function or by injecting
$resolver = app('LeeMason\Tenantable\Resolver');

//store the current tenant
$resolvedTenant = $resolver->getActiveTenant();

//purge the tenant from the default connection
$resolver->purgeTenantConnection();

//call the command
$result = \Artisan::call('commandname', ['array' => 'of', 'the' => 'arguments']);

//restore the tenant connection as the default
$resolver->reconnectTenantConnection();

未来计划

  • 添加测试
  • 将元项目添加到 laravel 配置