Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/238.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP MVC:控制器中的依赖项太多?_Php_Design Patterns_Model View Controller_Dependency Injection_Constructor - Fatal编程技术网

PHP MVC:控制器中的依赖项太多?

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

我正在从事一个个人HMVC项目:

  • 没有服务定位器,没有全局状态(如
    静态
    全局
    ),没有单例
  • 模型处理封装在服务中(服务=域对象+存储库+数据映射器)
  • 所有控制器都扩展了一个抽象控制器
  • 所有项目依赖项都是通过依赖项注入容器注入的
所有需要的依赖项都被注入抽象控制器的构造函数中。如果我想重写这个构造函数,那么我也必须在子控制器的构造函数中传递所有这些依赖项

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
    中了

我正试图找到一个优雅的方式来处理这项任务,我将感谢任何建议。谢谢。

我会回答我自己的问题。当我写这篇文章时,我已经很好地概述了许多有经验的开发人员对MVC和MVC结构中的依赖注入的建议

  • 构造函数注入是正确的选择。但似乎是这样 告诉我,按照这条路线,我会有太多的人 构造函数中的依赖项/参数。因此,给控制器 职责太多(读取请求的值,更改 域对象的状态、日志记录操作、请求视图 加载模板和呈现数据等)
  • 塞特注射也是需要考虑的解决方案。但是,在我的项目开发过程中,我意识到 这个解决方案真的(至少)不符合 我的控制器查看关系
  • 依赖项直接注入控制器 行动也给我带来了困难(但也带来了美好的时光),因为 我已经将url值作为操作参数和 我没有使用任何路由调度器
  • 为了能够 在每个控制器操作中都有可供我使用的对象。 工厂是一个很好的使用工具,但只是从 需要运行时对象,而不仅仅是减少 构造函数中的依赖项
  • 装饰图案也是一个不错的选择。但是,例如,如果您想在控制器操作中记录一些内容,那么 这不是一个解决方案:您仍然必须将记录器作为依赖项传递 (在构造器、设定器或动作中)
  • 我有一个想法,就是只注入所需的依赖项 子控制器。但接下来的问题是多重性 相应控制员的职责保持不变
因此,无论我做了什么,这些解决方案似乎都不完全适合我的HMVC项目的结构。因此,我进一步挖掘,直到我意识到缺失的环节是什么。为此,我向汤姆·巴特勒(Tom Butler)表示衷心的感谢,他是以下伟大文章的作者:


他的作品基于对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();