zf2 - 将依赖项注入控制器
zf2 - injecting dependencies into controller
zend-mvc 的最新更新由于逐步淘汰 ServiceLocatorAwareInterface 而导致兼容性中断。我在控制器中使用 servicelocator 来动态加载依赖项,例如:
class IndexController extends AbstractActionController
/**
*
* @return \UserManagement\Form\User\Details
*/
protected function getUserDetailsForm(){
return $this->getFormManager()->get('User\Details');
}
/**
*
* @return FormElementManager
*/
protected function getFormManager(){
return $this->getServiceLocator()->get('FormElementManager');
}
}
现在引发异常 (E_USER_DEPRECEATED) 并显示以下消息:
You are retrieving the service locator from within the class
User\Controller\IndexController. Please be aware that
ServiceLocatorAwareInterface is deprecated and will be removed in
version 3.0, along with the ServiceLocatorAwareInitializer. You will
need to update your class to accept all dependencies at creation,
either via constructor arguments or setters, and use a factory to
perform the injections.
我的问题是,将表单放入控制器的最佳方式是什么?我的服务层和其他特定于控制器的依赖项被注入到构造函数中,但我真的不想用控制器 可能 需要的所有形式来污染构造函数,我也不想要创建不会被使用的表单对象的开销。无法在控制器中创建表单,即 $form = new Form() 因为它们也是动态创建的,例如:
Module.php
public function getFormElementConfig ()
{
return array(
'factories' => array(
'User\Details' => function($sm){
$userMapper = $sm->getServiceLocator()->get('Model\User\Mapper');
$form = new \User\Form\Details($userMapper);
return $form;
}
)
);
}
拥有越来越多的特定控制器。
这样你就可以实例化一个控制器,然后必须准确地注入执行任何任务所需的所有对象。
如果它们共享的只是一个共同的 URL 路径片段,则将动作组合到一个控制器中是没有用的 class。从软件设计的角度来看,class 以不同的方法做大量独立的事情就是做得太多了。做太多反映在你必须注入的依赖项的数量上。
解决方案很少。
使控制器更小。更少的方法,更少的依赖。不过工厂比较多。
使用ZF2proxy manager。它实质上用代理对象替换了昂贵的对象实例化。
另一种选择是添加一个包装器或容器,通过表单元素管理器延迟加载表单。然后,您可以将此容器注入控制器或服务层。以这种方式使用服务定位器不是 "ideal",因为您失去了明确定义的 class 依赖项。
我有一个 FormElementLazyProvider
class and its associated factory 可能值得一试。
例如
$elementConfig = [
'create' => 'MyModule\Form\CreateForm',
'edit' => 'MyModule\Form\EditForm',
'delete' => 'MyModule\Form\DeleteForm',
];
$factory = function($serviceName, $elementName) use ($formElementManager) {
if ($formElementManager->has($serviceName)) {
return $formElementManager->get($serviceName);
}
return false;
};
$provider = new \ArpForm\Service\FormElementLazyProvider($factory, $elementConfig);
$provider->hasElement('create'); // true
$provider->getElement('edit'); // Callback executed and form object return
问题的症结在于服务定位器隐藏了控制器的依赖关系class。
Zend 框架指导您远离 ServiceRepository 模式并使用 DI 容器或使用构造函数注入或 setter 注入来使用适当的依赖注入。您也可以使用工厂来注入依赖项。
请阅读有关 Service Repository 的信息,许多人将其视为反模式。
zend-mvc 的最新更新由于逐步淘汰 ServiceLocatorAwareInterface 而导致兼容性中断。我在控制器中使用 servicelocator 来动态加载依赖项,例如:
class IndexController extends AbstractActionController
/**
*
* @return \UserManagement\Form\User\Details
*/
protected function getUserDetailsForm(){
return $this->getFormManager()->get('User\Details');
}
/**
*
* @return FormElementManager
*/
protected function getFormManager(){
return $this->getServiceLocator()->get('FormElementManager');
}
}
现在引发异常 (E_USER_DEPRECEATED) 并显示以下消息:
You are retrieving the service locator from within the class User\Controller\IndexController. Please be aware that ServiceLocatorAwareInterface is deprecated and will be removed in version 3.0, along with the ServiceLocatorAwareInitializer. You will need to update your class to accept all dependencies at creation, either via constructor arguments or setters, and use a factory to perform the injections.
我的问题是,将表单放入控制器的最佳方式是什么?我的服务层和其他特定于控制器的依赖项被注入到构造函数中,但我真的不想用控制器 可能 需要的所有形式来污染构造函数,我也不想要创建不会被使用的表单对象的开销。无法在控制器中创建表单,即 $form = new Form() 因为它们也是动态创建的,例如: Module.php
public function getFormElementConfig ()
{
return array(
'factories' => array(
'User\Details' => function($sm){
$userMapper = $sm->getServiceLocator()->get('Model\User\Mapper');
$form = new \User\Form\Details($userMapper);
return $form;
}
)
);
}
拥有越来越多的特定控制器。
这样你就可以实例化一个控制器,然后必须准确地注入执行任何任务所需的所有对象。
如果它们共享的只是一个共同的 URL 路径片段,则将动作组合到一个控制器中是没有用的 class。从软件设计的角度来看,class 以不同的方法做大量独立的事情就是做得太多了。做太多反映在你必须注入的依赖项的数量上。
解决方案很少。
使控制器更小。更少的方法,更少的依赖。不过工厂比较多。
使用ZF2proxy manager。它实质上用代理对象替换了昂贵的对象实例化。
另一种选择是添加一个包装器或容器,通过表单元素管理器延迟加载表单。然后,您可以将此容器注入控制器或服务层。以这种方式使用服务定位器不是 "ideal",因为您失去了明确定义的 class 依赖项。
我有一个 FormElementLazyProvider
class and its associated factory 可能值得一试。
例如
$elementConfig = [
'create' => 'MyModule\Form\CreateForm',
'edit' => 'MyModule\Form\EditForm',
'delete' => 'MyModule\Form\DeleteForm',
];
$factory = function($serviceName, $elementName) use ($formElementManager) {
if ($formElementManager->has($serviceName)) {
return $formElementManager->get($serviceName);
}
return false;
};
$provider = new \ArpForm\Service\FormElementLazyProvider($factory, $elementConfig);
$provider->hasElement('create'); // true
$provider->getElement('edit'); // Callback executed and form object return
问题的症结在于服务定位器隐藏了控制器的依赖关系class。
Zend 框架指导您远离 ServiceRepository 模式并使用 DI 容器或使用构造函数注入或 setter 注入来使用适当的依赖注入。您也可以使用工厂来注入依赖项。
请阅读有关 Service Repository 的信息,许多人将其视为反模式。