一个ZF2系统中有许多组件。每个组件都有自己的表示层,业务层和数据层。问题是组件Foo有一个使用组件Bar的数据层的控制器。
示例:
<inside modules, each module can be individually deployed or removed>
\modules
\Foo ; one module (this directory) can be added or removed
\view ; presentation layer (view) for all subcomponents
\Subcomponent1
\Action1
\Subcomponent2
\Action2
...
\src
\Subcomponent1
\Entity ; data layer (model)
\Controller ; business layer (controller)
\Service ; service layer (service)
\Subcomponent2
\Entity
\Controller
\Service
\Subcomponent3
...
\Bar
\view
...
\src
\Subcomponent1
...
\Baz
\src
\Subcomponent1
...
子组件与来自其他子组件的实体强烈耦合,通常来自不同组件。控制器和服务就是这种情况。这可以解决吗?
Foo \ Subcomponent1有一个FooSub1Service,它使用Bar \ Subcomponent1中的实体处理传递的数据并将其导入DB。 Baz \ Subcomponent1有一个AuthenticationService,它使用Bar \ Subcomponent1实体按ID等查找用户。
我知道依赖注入,但在这种情况下,每个子组件中都有EntityManager,并且它被指示按名称和PK查找实体,即find(“Bar \ Subcomponent1 \ Entity \ User”,123)。而且,当持久化实体时,我必须实例化任何具有外键的东西,即UserAddress并将其添加到用户。每次调用x = new NameOfEntity()时,我都会将子组件与子组件中的某个实体紧密耦合,通常来自不同的系统模块。
答案 0 :(得分:7)
在ZF2中,可以使用EventManager
减少模块之间的耦合,另请参阅here。
此外,module/config/module.config.php
用作Facade。
可以在任何模块的module/config/module.config.php
文件中定义所有实体 ONCE 。然后,其他模块可以使用ServiceManager
来解析它们的依赖关系。
ServiceManager
实现Service Locator pattern。
使用Facade(module.config.php
)和EventManager
,模块之间的耦合已成功减少。
答案 1 :(得分:0)
您无法始终删除所有依赖项。例如,auth模块通常依赖于某种形式的用户凭证。
您可以采取一种方法来减少与特定类的耦合,允许使用适配器替换依赖项。
例如,如果您希望能够使用不同类型的用户模块以及身份验证模块,则可以在身份验证模块中定义一个接口,该接口必须由用户模块中的适配器实现,以便兼容它。然后,向您的auth模块添加一个配置选项,允许用户更改使用的用户适配器实现。
根据复杂性,您还可以简单地为对象本身定义特定接口,而不是使用适配器。但是,这有时可能会在对象中添加不相关的函数或类似函数,可能会使其实现更难以理解。
最后,我建议不要试图在代码中实现这样的太多灵活性。除非你打算与全世界共享模块,否则你不太可能需要它,因为通常更简单地改变模块中具有硬依赖性的几行代码,而不是编写全新的接口和类。显然,您需要根据计划使用模块的方式来评估自己。
答案 2 :(得分:0)
不要直接访问实体或存储库。 为每个模块实现一个或多个服务,您可以为它们提供一个接口来清楚地实现这一点。
如果您像ORM Doctrine 2那样使用数据层,那么无论如何都会共享每个模块中的每个/实体文件夹。这使得可以在一个存储库中进行连接并获取已连接的实体。那不错。
不要滥用事件管理器,目的是减少依赖关系。使用共享服务并仅与这些服务一起使用。
当您想要呼叫整个应用程序并收集或需要答案时,请使用事件管理器。