Moo*_*zer 4 php dependency-injection overhead zend-framework2 zend-framework3
由于zend-mvc的2.7.0版本已ServiceLocatorAwareInterface被删除,因此$this->serviceLocator->get()控制器内部的调用也是如此.
这就是为什么几天前我对我的所有模块进行了大量重构,通过构造函数注入所需的服务/对象,使用工厂来处理大部分内容.
当然,我理解为什么这是更好/更清洁的做事方式,因为现在更容易看到家属.但另一方面:
这会导致繁重的开销和更多从未使用过的类实例,不是吗?
我们来看一个例子:
因为我的所有控制器都有依赖关系,所以我为所有控制器创建了工厂.
CustomerControllerFactory.php
namespace Admin\Factory\Controller;
class CustomerControllerFactory implements FactoryInterface {
public function createService(ServiceLocatorInterface $controllerManager) {
$serviceLocator = $controllerManager->getServiceLocator();
$customerService = $serviceLocator->get('Admin\Service\CustomerService');
$restSyncService = $serviceLocator->get('Admin\Service\SyncRestClientService');
return new \Admin\Controller\CustomerController($customerService, $restSyncService);
}
}
Run Code Online (Sandbox Code Playgroud)
CustomerController.php
namespace Admin\Controller;
class CustomerController extends AbstractRestfulController {
public function __construct($customerService, $restSyncService) {
$this->customerService = $customerService;
$this->restSyncService = $restSyncService;
}
}
Run Code Online (Sandbox Code Playgroud)
module.config.php
'controllers' => [
'factories' => [
'Admin\Controller\CustomerController' => 'Admin\Factory\Controller\CustomerControllerFactory',
]
],
'service_manager' => [
'factories' => [
'Admin\Service\SyncRestClientService' => 'Admin\Factory\SyncRestClientServiceFactory',
]
]
Run Code Online (Sandbox Code Playgroud)
SyncRestClientServiceFactory.php
namespace Admin\Factory;
class SyncRestClientServiceFactory implements FactoryInterface {
public function createService(ServiceLocatorInterface $serviceLocator) {
$entityManager = $serviceLocator->get('doctrine.entitymanager.orm_default');
$x1 = $serviceLocator->get(...);
$x2 = $serviceLocator->get(...);
$x3 = $serviceLocator->get(...);
// ...
return new \Admin\Service\SyncRestClientService($entityManager, $x1, $x2, $x3, ...);
}
}
Run Code Online (Sandbox Code Playgroud)
SyncRestService是一个复杂的服务类,它查询我们系统的某些内部服务器.它有很多依赖项,并且总是在请求来到CustomerController时创建.但这种同步服务只用于内部syncAction()的CustomerController的!我用简单的前$this->serviceLocator->get('Admin\Service\SyncRestClientService')内侧syncAction()所以才把它被实例化.
通常,看起来很多实例是在每个请求中通过工厂创建的,但是大多数依赖项都没有使用.这是一个问题,因为我的设计还是"通过构造函数进行依赖注入"的正常副作用行为?
在我看来,这是依赖注入通过构造函数的正常效果.
我认为您现在有两个选项(不是互斥的)来改善您的应用程序的工作方式:
拆分控制器,以便仅在需要时才会实现依赖关系.这肯定会产生更多的课程,更多的工厂等等,但是你的代码将获得更多的单一责任原则
您可以使用Lazy Services,这样,即使某些服务是整个控制器的依赖项,它们实际上只会在第一次被调用时进行实例化(因此,对于未调用它们的操作永远不会!)