Symfony2中基于请求的依赖性

时间:2014-05-27 16:49:01

标签: symfony dependency-injection multi-tenant

我正在开发一个多租户应用程序。租户在Request Listener中解析,它看起来或多或少如下:

/**
 * @Service
 * @Tag(name="kernel.event_listener", attributes={"event": "kernel.request", "method": "onRequest"})
 */
class TenantResolverListener extends ContainerAware
{
    public function onRequest(GetResponseEvent $event)
    {
        $request = $event->getRequest();

        // some magic stuff to detect tenant...

        $tenant = new Tenant($request->getHost());
        $this->container->set('tenant', $tenant);
    }
}

为了在我的应用程序中的任何位置轻松访问租户配置,我有了将租户注册为依赖项容器中的依赖项的想法。 这里的问题是,“租户依赖”在编译时是未知的,我无法将其直接注入其他服务。 (我必须注入容器并通过容器($this->container->get('tenant')))访问租户配置。

我认为这根本不是最好的解决方案,但我不太确定,如何解决问题。我的想法是:

  1. 注册默认租户,稍后将在TenantResolver中覆盖该租户。
  2. 在任何地方提前检测当前租户,但在哪里/如何?
  3. 不要将租户配置放入容器中
    1. 并将Configuration包装在自己的服务中,该服务定位当前租户并返回配置。 ($tenantResolver->getConfig())。
    2. 和......?
  4. 如果有人有经验,那么给我一些琐事是非常友好的。

    谢谢!

1 个答案:

答案 0 :(得分:3)

让自己成为TenantFactory服务,然后让租户服务使用它。

tenant_factory:
    class:  MyProjectBundle\Entity\TenantFactory

tenant:
    class:  MyProjectBundle\Entity\Tenant # Not used but still needed
    factory_service: '@tenant_factory'
    factory_method: get # The container will call $tenantFactory->get() when $tenant is needed.

// Request
$tenant = new Tenant($request->getHost());
$tenantFactory = $this->container->get('tenant_factory');
$tenantFactory->set($tenant);

class TenantFactory
{
    protected $tenant;
    public function set($tenant) { $this->tenant = $tenant; }
    public function get()        { return $this->tenant; }
}

// Controller
$tenant = $this->container->get('tenant');

您必须确保在调用租户相关服务之前触发了侦听器,但这不应该是一个问题。

当然TenantFactory并不是真正的工厂,但你明白了。实际上,您可以将其设置为真正的工厂(或存储库),并让您的请求侦听器注入主机名。

=============================================== ==============

更新:在发布答案后的几天,我正在阅读参考书(总是很危险)并且遇到了综合服务的概念。 http://symfony.com/doc/current/components/dependency_injection/advanced.html

不需要租户工厂。合成服务期望通过set添加对象。

# services.yml
tenant:
  synthetic: true

// Listener
$tenant = new Tenant($request->getHost());
$this->container->set('tenant', $tenant);