PHP MVC:控制器中的依赖项太多?
我正在从事一个个人HMVC项目:PHP MVC:控制器中的依赖项太多?,php,design-patterns,model-view-controller,dependency-injection,constructor,Php,Design Patterns,Model View Controller,Dependency Injection,Constructor,我正在从事一个个人HMVC项目: 没有服务定位器,没有全局状态(如静态或全局),没有单例 模型处理封装在服务中(服务=域对象+存储库+数据映射器) 所有控制器都扩展了一个抽象控制器 所有项目依赖项都是通过依赖项注入容器注入的 所有需要的依赖项都被注入抽象控制器的构造函数中。如果我想重写这个构造函数,那么我也必须在子控制器的构造函数中传递所有这些依赖项 class UsersController extends AbstractController { private $authen
- 没有服务定位器,没有全局状态(如
或静态
),没有单例全局
- 模型处理封装在服务中(服务=域对象+存储库+数据映射器)
- 所有控制器都扩展了一个抽象控制器
- 所有项目依赖项都是通过依赖项注入容器注入的
class UsersController extends AbstractController {
private $authentication;
public function __construct(
Config $config
, Request $request
, Session $session
, View $view
, Response $response
, Logger $logger
, Authentication $authentication // Domain model service
) {
parent::__construct(/* All dependencies except authentication service */);
$this->authentication = $authentication;
}
// Id passed by routing.
public function authenticateUser($id) {
// Use the authentication service...
}
}
依赖项列表将进一步增长。这需要改变。所以我在想:
- 将控制器与视图完全分开
然后他们将共享服务层。视图将不再属于控制器,响应将是视图的依赖项
- 在控制器
中使用setter injection,如
,请求
,会话
等李>记录器
- 仅在需要时在控制器操作中注入依赖项。
如
,请求
,会话
等李>记录器
- 使用decorator模式。
类似于操作调用后的日志记录- 实施一些工厂
- 若要构造函数,只需在子控制器上注入所需的依赖项
,这样就不再在
中了AbstractController
- 使用decorator模式。
我正试图找到一个优雅的方式来处理这项任务,我将感谢任何建议。谢谢。我会回答我自己的问题。当我写这篇文章时,我已经很好地概述了许多有经验的开发人员对MVC和MVC结构中的依赖注入的建议
- 构造函数注入是正确的选择。但似乎是这样 告诉我,按照这条路线,我会有太多的人 构造函数中的依赖项/参数。因此,给控制器 职责太多(读取请求的值,更改 域对象的状态、日志记录操作、请求视图 加载模板和呈现数据等)
- 塞特注射也是需要考虑的解决方案。但是,在我的项目开发过程中,我意识到 这个解决方案真的(至少)不符合 我的控制器查看关系
- 将依赖项直接注入控制器 行动也给我带来了困难(但也带来了美好的时光),因为 我已经将url值作为操作参数和 我没有使用任何路由调度器
- 为了能够 在每个控制器操作中都有可供我使用的对象。 工厂是一个很好的使用工具,但只是从 需要运行时对象,而不仅仅是减少 构造函数中的依赖项
- 装饰图案也是一个不错的选择。但是,例如,如果您想在控制器操作中记录一些内容,那么 这不是一个解决方案:您仍然必须将记录器作为依赖项传递 (在构造器、设定器或动作中)
- 我有一个想法,就是只注入所需的依赖项 子控制器。但接下来的问题是多重性 相应控制员的职责保持不变
他的作品基于对MVC概念的深入、论证充分的分析。它们不仅很容易理解,而且还通过不言自明的例子加以支持。一句话:这是对MVC和开发人员社区的杰出贡献 我将进一步写的只是用我自己的话来介绍他的原则,考虑以某种方式完成这些原则,提供一个更紧凑的视角,并展示我在项目中实施这些原则时遵循的步骤。这里描述的主题、想法、原则和工作流程的所有功劳都归汤姆·巴特勒所有 那么,我的HMVC项目中缺少的环节是什么?它被命名为“关注点分离” 为了简单起见,我将尝试通过仅引用一个控制器、一个控制器操作、一个视图、一个模型(域对象)和一个模板(文件)来解释这一点,并将它们引入到
用户
上下文中
在web上描述最多的MVC概念——我所研究的一些流行框架也实现了MVC——围绕着让控制器控制视图和模型的原则。为了在屏幕上显示一些东西,您必须告诉控制器-他进一步通知视图加载和渲染模板。如果此显示过程也意味着使用某些模型数据,则控制器也会操纵模型
按照传统方式,控制器创建和操作调用过程包括两个步骤:
- 创建控制器-传递所有依赖项,包括视图李>
- 调用控制器操作
$controller = new UserController(/* Controller dependencies */);
$controller->{action}(/* Action dependencies */);
这意味着,控制器负责一切。因此,难怪控制器必须注入如此多的依赖项
但是,控制器是否应该参与或负责在屏幕上有效显示任何类型的信息?不,这应该是我们的责任
class UserView {
//....
// Display information on screen.
public function output () {
return $this
->load('<template-name>')
->render(array(<data-to-display>))
;
}
//....
}
$controller = new UserController(/* (less) controller dependencies */);
$view = new UserView(/* View dependencies */);
$controller->{action}(/* Action dependencies */);
echo $view->output();
$model = new UserModel;
$controller = new UserController($model, /* Other controller dependencies */);
$view = new UserView($model, /* Other view dependencies */);
$controller->{action}(/* Action dependencies */);
echo $view->output();
$model = new UserModel;
$viewModel = new UserViewModel($model, /* Other view-model dependencies */);
$controller = new UserController($viewModel /* Other controller dependencies */);
$view = new UserView($viewModel, /* Other view dependencies */);
$controller->{action}(/* Action dependencies */);
echo $view->output();