leemason / tenantable
Laravel 多租户。
Requires
- laravel/framework: 5.2.*
Requires (Dev)
- phpunit/phpunit: ~4.0
This package is not auto-updated.
Last update: 2024-09-14 18:20:33 UTC
README
Laravel Tenantable 包旨在允许在无需访问数据库 ::connection('name')
的每个数据库调用的情况下,动态地启用基于数据库连接的多租户。
安装
只需通过 composer.json 为您的 Laravel 安装添加新的包即可。
composer require leemason/tenantable
然后执行 composer dump-autoload
更新 composer 后,将 ServiceProvider 添加到 config/app.php 中的 providers 数组中。理想情况下,您应该将其插入到 Illuminate\Database\DatabaseServiceProvider::class
之后,以确保其启动方法在数据库可用但在任何其他 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 会查找域名表以找到匹配项(如果找到,则使用 Eloquent 关系返回租户模型)。
- 找到匹配项后,将匹配项保存为活动租户,并将租户的数据库细节放置在
database.connections.tenant
配置中。 - 然后默认数据库连接更改为 'tenant',并清除连接(断开/重新连接)。
- 将
app.url
配置设置为租户的域名。 - 如果在任一表中找不到匹配项,将触发 TenantNotResolved 事件,并且不会发生任何配置更改。
以下是 artisan 控制台请求期间的工作方式
- Tenantable 将默认数据库连接的名称复制到
tenantable.database.default
配置区域。 - Tenantable 注册了一个控制台选项
--tenant
,您可以通过该选项提供 id、uuid、域名或 *、all 来为所有租户运行。 - Tenantable 检查是否提供了租户选项,如果没有提供,则不解析租户。命令正常运行。
- 如果找到匹配项,它将在执行命令之前解析租户(设置租户连接细节)。
- 如果您使用
--tenant
提供了*
或字符串all
,Tenantable 将为数据库中找到的每个租户运行命令,在每次运行之前设置活动租户。
解析器类
\LeeMason\Tenantable\Resolver
类负责解析和管理在 http 和控制台访问期间的活动租户。
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、域名、驱动程序、前缀、元数据和时间戳外)都进行了加密以确保安全,并在访问时解密,在保存时自动加密。
每个模型实例在创建时都会分配一个 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 配置中