1

我正在寻找对 MCV 中视图层的更好解释,特别是程序中的流程如何从控制器到视图,重点是在控制器和视图之间使用 1:1 关系时模型的状态。

在所有示例中,我都看到数据正在从控制器转发到视图,并且视图没有执行任何需要为特定控制器编写特定视图的特定操作。我是否误解了 1:1 的关系咒语?我发现的最新示例几天前发布在此处:https ://stackoverflow.com/a/18983927/1681418

class View
{
   public function render($templateFile, array $vars = array())
   {
      ob_start();
      extract($vars);
      require($templateFile);

      return ob_get_clean();
   }
}

我尝试为每个控制器创建特定的视图类,并且我目前有一个视图可以根据需要从模型中提取所有数据。从某种意义上说,我有一个非常明确的 do-stuff-to-the-model部分(=controller)和一个read-only-from-model部分(=view)。然而,我有一些缺点,我还没有找到一个整洁的解决方案,即:

  • 应该在哪里选择模板文件?
  • 视图如何知道模型中的错误?
  • 视图如何了解控制器中成功或不成功的命令/动作?
  • 出现错误时如何更改视图?或者,当用户状态发生变化时,我该如何正确地进行路由。

我在我的页面上呈现正确的输出没有问题,但我目前的方法感觉不对。**任何人都有一个使用域驱动设计的视图示例,模型作为一个层,而不是一个类?**

这个答案与我通常找到的答案非常相似,我不明白这种方法如何使用或需要 1:1 的关系。

我主要是在寻找示例,而不是代码审查,但无论如何我都在下面提取了一些代码作为示例。在这里,我通过调度程序调用控制器以进行访问控制和路由,然后通过同一个调度程序调用视图以再次检查访问。视图依次调用不同的表示对象,如果是 http 请求,则将数据分配给模板引擎,如果是 ajax 请求,则为 json。

class Controller
{
    public function login()
    {
        $this->serviceFactory
            ->build('recognition')
            ->authenticate($this->request->username, $this->request->password);
    }
}

class View
{
    public function login()
    {

        /** Prepare server response (i.e. state of the model) */
        $this->presentationObjectFactory
            ->build('serverresponse', true)
            ->setPresentationName('success')
            ->assignData($this->serviceFactory->build('modelLog')->getModelResponse('success'));

        /** Get current visitor information */
        $this->presentationObjectFactory
            ->build('visitor', true)
            ->assignData($this->serviceFactory->build('recognition')->getCurrentVisitor()); 

        return $this->serviceFactory->build('recognition')->getCurrentVisitor()->isLoggedIn() ? 
                    $this->indexAction() : /* Reroute to index of view */
                    $this->display('login.html'); /* Show the login template when unsuccesful login*/
    }
}

class PresentationObject
{
    public function assignData(Collection $visitors)
    {
        $dateformat = new DateFormat();
        $dateTime = new \Datetime();

        foreach($visitors as $visitor)
        {
            $dateTime->setTimestamp($visitor->timestamp);

            $this->assign_block_vars('visitor', array(
                'ID'                => $visitor->id,
                'USERNAME'          => $visitor->user->Username,
                'IP'                => $visitor->remote_addr,
                'HTTP_USER_AGENT'   => $visitor->http_user_agent,
                'LAST_SEEN_ONLINE'  => ucfirst($dateformat->formatDateDiff($dateTime)),
                'DEVICE'            => $visitor->getDevice(),
                'PLATFORM'          => $visitor->getPlatform(), 
                'BROWSER'           => $visitor->getBrowser(),  
            ));
        }
    }
}

我对 MVC 和领域驱动设计的知识和理解受到用户tereško的强烈影响,但我可能在此解释的查看部分误解了一些东西......

4

1 回答 1

1

控制器和视图之间的 1:1 关系有什么用途?

如果视图可以应用于多个工作流上下文/控制器/模型,则不需要严格的 1:1 规则。将视图和控制器分开,即使它们只一起使用并且可以合并,也是明确职责分离的最佳实践。它还使以后更容易交换和共享视图。

应该在哪里选择模板文件?

在您的情况下,您有一个 View 类,因此应该在那里定义它。在某些系统中,模板视图,通常在控制器或配置文件中选择。

视图如何知道模型中的错误?视图如何了解控制器中成功或不成功的命令/动作?

在某些架构中,模型在更新或任何其他操作期间将它们的问题返回给控制器。在控制器中,我通常将任何问题添加到用户消息堆栈中。然后在视图中我将这些消息输出给用户。

出现错误时如何更改视图?或者,当用户状态发生变化时,我该如何正确地进行路由。

我见过有很多不同的处理方式。最强大的解决方案是让您的控制器将下一个工作流程步骤传递给视图。视图基本上应该尽可能地与任何业务逻辑无关。

任何示例代码对于 SO 来说都太长太复杂了。我将从好的 MVC 框架教程开始:

于 2013-10-12T23:49:49.063 回答