我正在创建一个受MVC启发的PHP框架,主要用于学习目的。 我基本上已经创建了框架,并在此框架上构建了一个应用程序,并在不断改进框架。
对于这种体系结构的某些方面,我仍然感到困惑/不确定,目前,我正在质疑我对View部分的实现。
我如何设置框架:
这是一个非常简单的设置,例如:您进入URL /post/post_id
,这将加载index.php,它将实例化路由器。然后,路由器将检查该URL,并根据该URL实例化正确的控制器和方法。在这种情况下,它将是PostController,并且该方法将是默认方法,该方法将使用post_id
从相关模型中获取帖子数据。接下来,控制器将设置一个“数据”变量,该变量将保存要传递给View的数据,这是我感到困惑的地方-如果它发送到自己的View对象(专用于PostController的视图类文件),还是所有控制器都用来加载html文件的通用View类?
在我的控制器将数据发送到View类的那一刻,此数据包括应包含/显示的模板文件以及页面的实际数据(我们从模型通过控制器获得的信息)。
我的问题是这个
这种类型的系统应该有一个View对象,该对象根据将什么数据提供给“ render”方法来呈现所有视图(html文件),或者每个最终将数据发送到View的控制器都应该拥有自己的视图对象查看对象/类?
意思是,应该PostController向通用视图类发送一个请求,该请求与所有控制器用于呈现页面的请求相同,或者应该将PostController发送给专用的View类(如果使它更清晰,则称为PostView),然后此类将呈现特定的html文件?
基本上,对于所有将呈现该控制器告诉其的html文件的控制器,它应该是一个View类,或者如果应该有许多View类,则每次页面加载一个。
注意: 我知道已经有很多关于PHP中的MVC的问题,但是我在任何答案中都找不到我的问题的答案。
答案 0 :(得分:0)
IMO的最佳方法是让此View
或Template
类仅使用一种简单的方法render(string $templateName, array $context = [])
来完成与视图相关的所有工作。
这允许轻松扩展或创建适配器。您应该使您的控制器使用此方法。如果在框架中使用DI容器,则可以执行TemplatingAwareInterface
并将其实现为允许setter注入的特征。从服务容器中获取时,这将注入模板服务。这样,您可以在控制器中使用$this->templating->render()
,而不必使其成为全局变量,也不必在控制器内部构造模板服务,也无需将容器注入控制器。
为每种类型的控制器设置一个视图类很麻烦,维护起来比较困难,我真的没有找到原因。
答案 1 :(得分:0)
有关MVC的一些知识:
在原始MVC模式(由Trygve Reenskaug在1979年提出)中,控制器更新模型,模型通知视图有关更改,然后视图从视图中获取其数据。尽管这种模式被认为是用于桌面应用程序的-每个M-V-C“三合一”蜂鸣都与窗口中的单个控件(按钮,文本框,复选框等)相关。因此,屏幕上的每个控件都有一个“附加”的MVC。
由于在Web应用程序中,不存在(或不能存在)“模型到视图”通知步骤,因此无法将原始模式直接应用于它们。 但是,仍然可以相对轻松地实现最相似的方法:控制器更新模型,视图从模型中提取数据(与控制器无关)。我认为它叫做“ Web MVC Model 2” 。
Web MVC有很多变体。您正在使用一种方法,其中控制器担当模型和视图之间的中介角色。 因此,控制器是与模型通信的唯一组件。
视图的职责:
视图组件的职责是 表示逻辑 -控制器完全不应该承担。除了加载和呈现模板文件之外,这种逻辑还涉及从模型中获取的数据的 准备工作 。准备的结果最好是原始类型的值(字符串,布尔值,整数,数组等)的列表,这些类型可以在加载和渲染过程中轻松地“注入”到模板文件中。 >
演示逻辑示例:
示例1: :如果您要获取值123.45
(从表amount
的列revenues
中获取)从模型中,表示逻辑将包括将其格式化为字符串123.45 USD
,以便显示在模板文件中。
示例2: 使用如下代码段将获取的日期值28/05/2019
格式化为2019-05-28
:
$fetchedDateFromModel = '28/05/2019';
$time = strtotime($fetchedDateFromModel);
$formattedDate = date('Y-m-d', $time);
然后将$formattedDate
的值“注入”到模板文件中。
示例3: :根据一些模型数据设置布尔值,以便在模板文件中用于确定按钮(“获得奖励” )应该处于活动状态。
$paidAmount = 512.79; /* model data */
$isActiveGetBonusButton = false;
if ($paidAmount > 500) {
$isActiveGetBonusButton = true;
}
答案(关于您选择的MVC方法):
通过在所有控制器中使用View
实例,您将被迫在每个控制器中执行特定的表示逻辑-在将其结果(例如,准备值列表)传递给使用的View
之前例如,为了进一步将其“注入”到特定的模板文件中。
如果您要为控制器类(例如{)实现专用的视图类(例如PostView
-最好继承包含View
方法的基类render()
), {1}})-一对一的关系,但把它看作是一个松散的关系! -您可以以 未准备的形式 将从模型中获取的数据从控制器传递到视图。然后,视图类将正确承担准备在实际加载和呈现特定模板文件之前显示的数据的责任。例如。执行整个特定的表示逻辑的方法。
注意:在“ Web MVC模型2” 中-理想情况下,控制器不了解视图组件-上面的论点更为明显:>
PostController
仅更新模型(需要更新步骤时); PostController
从模型中获取数据,准备进行显示并显示(例如,通过加载和呈现PostView
之类的模板文件)。换句话说,视图组件自己执行整个表示逻辑。