我正在尝试使用 Laravel 5 构建一个多租户应用程序。我知道已经存在诸如 Hyn 和 AuraEQ 之类的软件包,但我仍然觉得这些很难理解,我想制作自己的(简化)版本。这样我就可以确切地知道引擎盖下发生了什么。在开始之前,我已经阅读了互联网上的几乎所有内容,但是关于这个主题的信息并不多。
我想到的方法非常简单:
- 定义 中的租户
app/config/tenant.php
和对应的数据库连接app/config/database.php
。我认为将租户存储在“主”数据库中是多余的。 - 注册服务提供商以启用多租户
- 在检测(活动)租户的 IoC 容器中注册一个 Singleton
- 扩展所有 Eloquent 模型并覆盖
getConnectionName()
活动租户数据库中的查询
每个网站(租户)在存储路径中都有自己的文件夹。假设我有一个名为“coding.com”的网站,路径将类似于:app/storage/tenants/coding-com
. 租户当前拥有自己的视图和路线。
到目前为止一切顺利,这是代码:
class TenantServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* @return void
*/
public function boot()
{
$this->app->singleton('Tenant', function () {
$tenants = config('tenant.hosts');
$host = Request::server('HTTP_HOST');
if(array_key_exists($host, $tenants)) {
return $tenants[$host];
}
return null;
});
$tenant = $this->app->make('Tenant');
$directory = tenant_path($tenant);
if($tenant && is_dir($directory)) {
// Load views from the current tenant directory
$this->app['view']->addLocation($directory . '/views');
// Load optional routes from the current tenant directory
if(file_exists($directory . '/routes.php')) require_once $directory . '/routes.php';
}
// Load base views, these will be overridden by tenant views with the same name
$this->app['view']->addLocation(realpath(base_path('resources/views')));
}
}
定义租户:
return [
/**
* Base path of the tenant's directory.
*/
'path' => storage_path('tenants'),
/**
* This is where the tenants are defined.
*/
'hosts' => [
'coding.com' => [
'id' => 'coding-com', // Connection within config/database.php is also named coding-com
'https' => false,
],
'other.com' => [
'id' => 'other-nl',
'https' => false,
]
]
];
而且我必须使用一个名为“TentantModel”的类来扩展每个 Eloquent 模型,它会覆盖该getConnectionName()
方法:
/**
* Get the current connection name for the model.
*
* @return string
*/
public function getConnectionName()
{
$tenant = app()->make('Tenant');
if($tenant) {
return array_get($tenant, 'id');
}
return parent::getConnectionName();
}
我为大量代码道歉,但这使这个想法更容易理解。
这给我带来了几个问题:
- 我将如何为每个租户单独管理资产?
- 使用 Singleton 是否对这种方法有意义?这是我唯一能想到的拥有某种全局变量并且它工作正常,但我怀疑 Singleton 是否适用于这种东西。
- 这种方法是否有任何缺点,我在考虑时没有考虑到这些问题?
只回答一个将不胜感激。提前致谢!