Laravel多帐篷应用方法

时间:2015-12-19 20:31:18

标签: php laravel-5 assets multi-tenant multi-database

我正在尝试使用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是否适用于这类东西。
  • 这种方法是否有任何缺点,在考虑这个问题时我没有考虑到这些因素?

回答一个人将不胜感激。提前谢谢!

0 个答案:

没有答案