与ASP.NET MVC类似,我想在控制器及其依赖项上实现松散耦合。
我想实现以下目标:
class TimesheetController extends AbstractActionController
{
private $userRepository;
function __Construct()
{
$sm = $this->getServiceLocator();
$this->userRepository = $sm->get('Application\Model\Concrete\TGUserRepository');
}
// ... becomes
function __Construct( IUserRepository $userRepo ) // the controller is injected with a bound repository so I do not have to implicitly specify it in the construct
{
$this->userRepository = $userRepo;
}
// And this is my action
public function ListAction()
{
$users = $this->userRepository->Users();
$view = new ViewModel( array( "Users" => $users ) );
$secondarySidebarView = new ViewModel();
$secondarySidebarView->setTemplate('something/poo');
$view->addChild($secondarySidebarView, 'something');
return $view;
}
// .... and more
}
我该怎么做?
我想可能会有一个绑定函数说当需要IUserRepository时,去制作一个TGUserRepository
Bind("IUserRepository", "TGUserRepository");
我见过Laravel完全按照我的意愿行事:
答案 0 :(得分:0)
控制器的调用方式与ZF2中的服务完全相同,因此当您在config / module.config.php中声明一个新控制器时,不是在'invokables'中注册它,而是可以在'factory'中注册它例如:
'controllers' => array(
'invokables' => array(
'Application\Controller\Index' => 'Application\Controller\IndexController',
),
'factories' => array(
'Application\Controller\Timesheet' => function ($sm) {
$userRepository = $sm->get('Application\Model\Concrete\TGUserRepository');
$controller = new \Application\Controller\TimesheetController($userRepository);
$controller->setServiceLocator($sm);
return $controller;
},
),
),
顺便说一下,当您使用服务定位器来获取实例和服务时,您只能限制与ServiceLocator的耦合,您可以在测试中轻松“模拟”服务,或者由另一个服务替换服务来完成工作。
当然,随着应用程序的增长,ServiceLocator成为一大堆服务和实例。我变得不那么可读,很难知道'你在里面有什么'。通过在控制器中准确传递您所期望的(并且是必需的),我理解您的观点。