我正在寻找对 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();
}
}
我尝试为每个控制器创建特定的视图类,并且我当前有一个视图,该视图在需要时从模型中提取所有数据。从某种意义上说,它很干净,因为我有一个非常定义的模型部分(=控制器)和一个从模型只读的部分(=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 的强烈影响,但我可能误解了这个解释的视图部分的一些东西......
控制器和视图之间的 1:1 关系有什么用途?
如果视图可以应用于多个工作流上下文/控制器/模型,则不需要严格的 1:1 规则。 将视图和控制器分开,即使它们只能一起使用并且可以合并,也是明确职责分离的最佳做法。它还使以后交换和共享视图变得更加容易。
应在哪里选择模板文件?
在您的情况下,您有一个 View 类,因此应该在那里定义它。在某些系统中,模板是视图,通常在控制器或配置文件中选择。
视图如何了解模型中的错误? 视图如何了解控制器中成功或不成功的命令/操作?
在某些体系结构中,模型在更新或任何其他操作期间将其问题返回给控制器。 在控制器中,我通常会将任何问题添加到用户消息堆栈中。然后在视图中,我将这些消息输出给用户。
出现错误时如何更改视图?或者,如何在用户状态更改的情况下正确执行路由。
我见过以多种不同的方式处理这个问题。 最可靠的解决方案是让控制器将后续工作流步骤传递到视图。 该视图基本上应尽可能与任何业务逻辑无关。
对于 SO 来说,任何示例代码都太长和复杂。 我会从好的MVC框架教程开始:
- 拉
- 拉维尔验证规则
- 代码点火器表单验证
- Symfony验证