【问题标题】:MVC : Is this the correct sequence to initialize & invoke MVC layersMVC:这是初始化和调用 MVC 层的正确顺序吗
【发布时间】:2018-07-20 07:08:11
【问题描述】:

我正在尝试学习基于 php MVC 的网页开发。起初我真的认为它只是将项目解耦为 3 个类模型、视图、控制器。但是在之前的帖子 cmets 的帮助下,我意识到这些不是类而是相反,它们是层

// don't be confused my class/OOP style, it is just for conceptual purpose
Model.php Layer related code   
View.php Layer  related code   
Controller.php Layer related code   

User: index.php
//initiating model layer related things
$m = new Model;
// initiating Controller layer related things
$v = new Controller($m);
// initiating view layer related things
$c = new View($m, $c);

但是,互联网上有许多 MVC 示例有时令人困惑和冲突。例如,一些建议:控制器可以访问模型和视图,而其他建议视图可以访问两者。所以请任何人检查我的代码顺序以确保它确实遵循 MVC 模式。

【问题讨论】:

  • MVC 有许多不同的解释,尤其是在 web 环境中。据我了解,控制器将作用于模型,视图将从模型中提取数据。视图和控制器不能相互了解。我倾向于同意 viewmodel != model.在某些框架中,控制器操作会更新模型并选择一个视图,但控制器仍然不会直接更新视图,而是通过将模型传递给视图
  • 我也发布了一些代码,如果你也对实际部分感兴趣的话。祝你好运。

标签: php model-view-controller


【解决方案1】:

在我看来来自 PHP 和 Javascript 模型 - 您的数据所在的位置,并被操纵以进行提取。 控制器 - 从模型和其他任何东西中提取数据,并为用户塑造成某种东西,可以是视图或端点。 View - 从 Controller 获取数据并将数据传递给控制器​​的 UI,即表单。 View 从不与 Model 交互。我喜欢的一个概念是头重脚轻的模型,轻型控制器。 我个人不认为他们是硬性规定,只是指导

【讨论】:

    【解决方案2】:

    在桌面应用程序的原始 MVC 模式中(由 Trygve Reenskaug 在 1979 年提出),控制器更新模型,模型通知视图有关更改,然后视图从中提取数据。此外,M、V 和 C 组件被认为与窗口中的单个控件(按钮、文本框、复选框等)相关。如果屏幕上有 15 个控件,那么每个控件都“附加”了一个 MVC。

    在 Web 应用程序中,通知步骤(从模型到视图)不存在。但是 M、V 和 C 组件之间的其余关系保持不变。因此,在 Web MVC 中,控制器更新模型,视图从中提取数据。此外,所有三个组件都与网页相关,而不是与网页上的单个控件相关。

    控制器和视图都不应使用域对象,例如entities(作为领域模型的一部分)直接。它们仅通过应用程序服务(也称为用例)与域模型进行(单独)通信。这些服务可以将(多个)任务委托给(多个)域服务。进而利用 域对象 (entities)。如果需要外部组件和/或服务(例如 持久层 中的组件和/或服务,例如存储库、数据映射器),则域模型和它们之间的连接是通过使用相应的接口。这些也是领域层的一部分。

    视图不应该访问控制器。为什么要这样做呢?控制器解释用户发送的请求(通过 HTTP 协议,在 Web 应用程序中),并将所有与域相关的工作推迟到域中的服务层,并将请求数据传递给它。所以控制器只影响域层的变化。另一方面,视图仅从域层请求数据。它也通过服务来做到这一点。所以视图从域中读取。因此,在您的代码中,视图应该只接收 $m 作为参数。

    关于视图直接从域层提取数据有一个重要方面:如果视图期望简单地直接呈现从域接收到的数据,那么这意味着域将负责准备(例如格式化)视图的数据。但这意味着模型应该知道准备数据的格式。例如。域模型必须了解位于其边界之外的组件。这可不好。所以视图的作用是接收未准备好的数据,为网页格式化,并呈现出来。总之,视图执行表示逻辑。

    在下面的链接中,Robert C. Martin 进行了精彩的演示,介绍了应如何在应用程序中涉及的组件之间分离关注点,从而形成良好的应用程序架构。将上述想法与演示文稿中提出的想法进行比较,您会发现它们之间存在两个差异。

    第一个是,在视频中,表示层由演示者、视图模型和视图组成。而在上述 Web MVC 中,整个呈现逻辑仅由视图执行 - 这不是很好。

    第二个是,在视频中,将要由表现层处理和显示的数据从控制器通过领域层推送到表现层。现在试着想象你自己,那个演示者依赖于一个交互器(实际上是一个应用程序服务,一个用例)。例如。从演示者指向领域层的箭头描述了一种依赖关系,而不是继承关系。那么演示者的角色就是将信息拉出领域层。与上面介绍的 Web MVC 的类比是显而易见的。

    资源:

    Keynote: Architecture the Lost Years - 由Robert Martin 提供的演示文稿,在Creative Commons Attribution ShareAlike 3.0 下获得许可。


    示例 1(在 index.php 中):显示数据

    用户在浏览器的地址栏中输入 URL http://localhost/questions/12345,并期望一个带有问题和多个 cmets 的 html 页面。因此 HTTP 方法是“GET”。所以不需要控制器,只需要一个视图(用于从域模型读取和显示数据)。

    <?php
    
    namespace Test\MvcExample;
    
    use Lib\Http\Message\Response;
    use Lib\Router\RouteCollection;
    use Lib\Http\Message\ServerRequest;
    use Lib\Http\MessageEmitter\ResponseEmitter;
    
    /*
     * -----------------------------------------
     * Before dispatching by a front-controller.
     * -----------------------------------------
     */
    $routes = new RouteCollection();
    $routes->add('GET', '/questions/{id:\d+}', [
        'view' => [QuestionsView::class, 'index'],
    ]);
    
    $request = new ServerRequest('GET', '/questions/12345' /* , other args */);
    $response = new Response(/* args */);
    
    /*
     * ------------------------------------------------------------------
     * Dispatched by a front-controller.
     * Route params are saved into the attributes list of server request.
     * ------------------------------------------------------------------
     */
    $view = new QuestionsView(new Template(), new QuestionsService(), new CommentsService());
    
    $response = $view->index($response, $request->getAttribute('id'));
    
    /*
     * ----------------------------------------
     * After dispatching by a front-controller.
     * ----------------------------------------
     */
    $responseEmitter = new ResponseEmitter();
    $responseEmitter->emitResponse($response);
    

    示例 2(在 index.php 中):更新和显示数据

    在 URL http://localhost/questions/edit/12345 处,用户在带有属性 action="/questions/update" 的表单中编辑问题,然后单击提交按钮“更新”。因此 HTTP 方法是“POST”。因此需要一个控制器(用于更新模型层)和一个视图(用于从模型层读取和显示数据)。

    除了使用视图之外,还可以更改为其他要求。例如,要使用演示者和视图,两者都共享一个视图模型。

    <?php
    
    namespace Test\MvcExample;
    
    use Lib\Http\Message\Response;
    use Lib\Router\RouteCollection;
    use Lib\Http\Message\ServerRequest;
    use Lib\Http\MessageEmitter\ResponseEmitter;
    
    /*
     * -----------------------------------------
     * Before dispatching by a front-controller.
     * -----------------------------------------
     */
    $routes = new RouteCollection();
    $routes->add('POST', '/questions/update', [
        'controller' => [QuestionsController::class, 'updateQuestion'],
        'view' => [QuestionsView::class, 'getQuestionUpdated'],
    ]);
    
    $request = new ServerRequest('POST', '/questions/update' /* , other args */);
    $response = new Response(/* args */);
    
    /*
     * ----------------------------------
     * Dispatched by a front-controller.
     * ----------------------------------
     */
    $questionsService = new QuestionsService();
    
    $controller = new QuestionsController($questionsService);
    $controller->updateQuestion($request);
    
    $view = new QuestionsView(new Template(), $questionsService);
    
    $response = $view->getQuestionUpdated($response, $request);
    
    /*
     * ----------------------------------------
     * After dispatching by a front-controller.
     * ----------------------------------------
     */
    $responseEmitter = new ResponseEmitter();
    $responseEmitter->emitResponse($response);
    

    【讨论】:

      猜你喜欢
      • 2013-03-07
      • 2017-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-18
      • 2013-10-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多