理解PHP中的MVC视图

Edu*_*eda 32 php model-view-controller coding-style

我在阅读MVC中的Views概念时似乎存在问题,根据我所读到的,它们是在应用程序中管理表示的层,但是我一直在阅读的许多材料似乎都有所不同.来自PHP Master.com的这个问题.

View是一个具有返回一些HTML代码的函数的类,HTML的其余部分在哪里?它应该放在访问此View代码的独立.html页面中吗?

在本文中,来自php-html.net的View是一个扩展名为.php的简单HTML文件,但它们如何访问这些数据?我require()在第一个教程中看不到或类似于实例化.

ter*_*ško 76

注意: MVC和MVC启发的模式是高级构造.它们用于代码库,其中普通的面向对象(遵循SOLID和其他指南)代码开始变得难以管理.通过引入此模式,您将强加其他约束,然后允许您包含非常复杂的应用程序.MVC 不适用于"hello world"应用程序.


让我们从头开始 ...

MVC和MVC启发的设计模式背后的核心理念是Separation of Concerns.所述分离是双重的:

  • 模型层与UI层分开:
  • 视图与控制器分开

在此输入图像描述

模型层(不是"类"或"对象")将包含几组结构,每个结构都处理业务逻辑的不同方面.主要部分是:

  • 域对象:验证,业务规则
  • 存储抽象:来自域对象的数据的持久性和缓存
  • 服务:应用逻辑

存储库,工作单元和其他工具中也可能存在混合.

UI层主要由视图和控制器组成.但他们都利用服务与模型层互动.服务为控制器提供了更改模型层状态的方式,以及视图根据新状态收集信息的方式.

在Web的上下文中,视图和控制器形成松散的对,因为Web应用程序展示了请求 - 响应特性.

应该注意的是,虽然控制器可以直接改变当前视图的状态,但更常见的是这些改变是通过模型实现的.直接更改视图的一个原因是,例如,当您需要使用JSON响应而不是XML时.

虽然也可以说可以简单地为每种输出格式实例化不同的视图并利用多态性.


什么不是观点?

人们普遍存在一种误解,即视图只是美化模板文件.在发布RubyOnRails原型框架后,这个错误变得非常流行.

视图不是模板.如果你这样使用它们,你就打破了MVC和MVC启发模式背后的核心原则.

如果您假装模板是视图,则会对您的体系结构产生巨大影响.视图中没有表示逻辑的位置,因此您可以在控制器或模型层中推送表示逻辑.通常的选择是"控制器",因为大多数人都明白表示逻辑在模型层中没有位置.

从本质上讲,这会导致视图和控制器的合并.


什么是观点?

视图的职责是处理表示逻辑.在web的上下文中,视图的目标是产生对用户的响应(顺便说一下,浏览器不是人类).

从技术上讲,可以创建客户端视图,即用户Web套接字来观察模型层,但实际上它实际上是不可能实现的.特别是在PHP环境中.

要创建此响应视图,请从模型层获取信息,并根据收集的数据,通过将数据分发到模板并呈现或有时简单地发送HTTP位置标头来组装响应.

使用Post/Redirect/Get时,重定向部分由视图执行,而不是人们倾向于执行的控制器.


高度主观的位:

最近我更倾向于使用以下方法与MVC交互:

  // the factory for services was injected in constructors
  $controller->{ $method.$command }($request);
  $response = $view->{ $command }();
  $response->send();
Run Code Online (Sandbox Code Playgroud)

$method是当前的REQUEST_METHOD,已被调整为类似REST的API,而$command人们通常称之为"动作".控制器具有单独的例程GETPOST(其他)请求.这有助于避免if在每个"动作"中都相同.

在视图中我称之为两种方法.首先是动态调用来收集数据.第二个目的是创造某种类型的回应.

警告:我怀疑此设置包含SRP违规.采用它作为你自己可能是一个坏主意.


干什么?

您可能已经注意到,将视图作为实例存在轻微问题.你最终会重复一些代码.例如:菜单或分页.

让我们看一下分页.分页包含逻辑,但这个逻辑与模型层无关.该模型没有"页面"的概念.相反,这一点逻辑将驻留在UI层中.但是如果你的每个观点都包含或继承了分页,那么它将明显违反SRP(实际上还有其他一些原则).

为了避免这个问题,您可以(并且应该,恕我直言)在您的视图中引入演示文稿对象.

注意:虽然福勒称他们为"演示模型",但我认为这个名称只会增加整个"什么是模型"的混乱.因此,我建议将它们称为"演示文稿对象".

表示对象处理重复的逻辑.这使得视图"更轻",并且在某些方面开始反映来自模型层的服务结构.

表示对象和模板之间的交互变得类似于域对象和数据映射器之间的交互.


我总是需要这一切吗?

不会.这种特定的方法主要面向代码,其中UI层具有很多复杂性,您需要将输入和表示的处理分开才能理智.

如果您的应用程序具有非常简单的UI,例如..嗯..您正在为更大的集成项目制作REST API.在这种实用选项中,可以将每个控制器 - 视图对合并为单个类.

在重构遗留代码库时,这也是一个很好的步骤,因为这种不太受约束的方法可以让您移动整个旧代码块.当您隔离了这些旧代码片段并进行检查时,一切仍然有效(因为遗留代码从未进行任何测试......这就是它的"遗留"),然后您可以开始进一步分解它,同时专注于分离业务逻辑来自UI.


PS我自己仍然在努力找出如何最好地处理观点的方法.这篇文章不是一个答案,更像是我目前理解的快照.


J. *_*uni 11

第二个教程是Code Igniter框架的工作方式,也是我习惯的方式.即使根本不使用框架,我也会遵循它.

实际上,开发人员必须将类似MVC的原则付诸实践,否则他/她甚至可以使用最类似MVC的框架来制作烤宽面条或意大利面条.

使用"PHP文件作为视图模板"的方法,理想情况下,人们会使用最小的PHP语句,基本上只用于repeat-structures(foreach ($array as $item)),basic conditionals(if ($boolean))和echo- 就像它确实是模板语言一样,仅此而已.

因此,<?php ?>视图模板文件中的标记应仅仅是占位符,而不是其他内容.

不应在视图模板文件中执行数据库查询,访问模型,计算等.它应该被视为带有占位符的HTML文件.(使用相关的CSS和JavaScript.当应用程序依赖JavaScript/AJAX时,事情可能会变得更复杂......)

遵循这些简单的原则,我们有效地将表示与业务逻辑分开.即使听起来如此简单,我也厌倦了处理不遵循它的Code Igniter代码.有些人使用"辅助函数"来伪装模型/数据库调用 - 并认为这是一个好习惯!:-)

您没有require在这些PHP视图模板文件中看到它们,因为它们是"视图构建"方法所必需的.

当然,不应该echo和/或print来自控制器和模型功能.这也很简单,但我也厌倦了看到意大利面条代码从CI控制器方法中回显出HTML.

在实践中,控制器调用模型方法,为视图构建所有必要的数据,并且作为最后一步,调用视图(即构建并输出它),将先前已经获得的数据传递给它.

说得通?我不知道我是否回答了你的问题.至少,这些是我的"2美分".

  • @tereško:好的,我已经将"MVC"改为"类似MVC"以满足纯粹主义者.事实上,我已经阅读了其他问题的答案,并了解到我应该说"MVP",因为他们所谓的"控制器"实际上是"演示者"! (2认同)