当您尝试在代码库中应用SoC 原则时,您会遇到多个问题。
而且,如何处理视图和控制器之间的通信是比较明显的一种。那是因为,如果你把它搞砸了,就没有抽象可以把它全部隐藏起来。
两种主要的方法是Supervising Controller和自治视图(没有文章,但你可以从this和this中推断出一些)。
监督控制器
这种方法最适合较小的应用程序(嗯 .. 对于较大的“小”值,因为非常小的项目并不真正需要 MVC 的架构膨胀)。它基本上看起来像这样:
/* in a controller */
public function verifyEmail(Request $request)
{
$identity = $this->search->findEmailIdentityByToken(
$request->get('token'),
Identity::ACTION_VERIFY
);
$this->registration->verifyEmailIdentity($identity);
$body = [
'status' => 'ok',
];
return new JsonResponse($body);
}
本质上,您所拥有的是一个控制器,它与业务模型交互并(在必要时)用数据填充视图。然后它会导致视图被渲染并返回响应。
根据我自己的经验,我发现这是编写后端应用程序时使用的最佳方法,预计只能通过类似 REST 的 API 进行操作。
正如您在示例中看到的那样,这种情况下的“视图”非常微不足道。它基本上是数组,您将其呈现为 JSON(提供的代码实际上会这样做 - 它是从真实项目中复制的)。
注意:
如果您的意图是完全实现 REST as it was proposed(不仅仅是类似 REST 的资源端点)和/或
有resource expansion的功能,那么这种做法可能是错误的,甚至是有害的。
自主视图
当您的表示逻辑变得复杂或必须为具有相同功能的同一应用程序提供不同的 UI(例如,具有网站和 REST API 的单个应用程序,同时具有 xml 和 json 接口),那么使用监督控制器就成了一个球并用链子挂在你的脖子上。您的控制器开始不受控制地增长,您的项目甚至可以在投入生产之前被描述为“遗留代码库”。
这就是您使用这种方法的地方。
您将视图和控制器用作完全独立的类,并在同一层与它们的实例进行交互(例如:引导阶段)。它最终看起来像这样:
/* in /src/application.bootstrap.php */
$command = $request->getMethod() . $parameters['action'];
$resource = $parameters['resource'];
$controller = $container->get("controllers.$resource");
if (method_exists($controller, $command)) {
$controller->{$command}($request);
}
$view = $container->get("views.$resource");
if (method_exists($view, $command)) {
$response = $view->{$command}($request);
$response->send();
}
同样,来自不同实时项目的示例,该项目也使用 DI 容器。在这种情况下,只有一个 UI(因此,在创建视图实例时没有“类型”前缀),这意味着代码可以利用控制器视图之间的 1:1 关系(如果你需要多个 UI)。
这种情况下的控制器基本上只“写入”到模型层。并且视图(也可以从模型层访问服务)仅执行“读取”并提取仅信息,这是填充模板和呈现模板所需的信息。
而且,如果您的演示逻辑进一步增长,最好开始添加presentation objects,它将包含演示逻辑的重复部分(例如,决定侧边栏中的哪个菜单项必须展开,哪个菜单项子菜单项必须突出显示),这对于多个视图很常见。
如果您的后端应用程序只处理 API,那么这种方法可能过于复杂,除非您正在做“注释”部分中提到的事情之一。
...也许这有点帮助