MVC 概述
下图描绘了在 Joomla 中使用的 MVC 模式。这同时适用于后台管理端和前端网站。
基本元素
在本部分中,我们将覆盖图中显示的 4 种类型的类。在组件中,你可能会拥有若干控制器、视图和模型类,以及(如果组件使用数据库中的自己表或表格)针对组件拥有的每个数据库表的一个表类。
控制器
您的控制器代码将在每次有传入的 HTTP 请求路由到您的组件时运行。控制器负责分析用户的请求,检查用户是否可以执行该操作以及确定如何满足该请求。后者可能涉及
- 确定哪些模型(或模型)将需要满足该请求,并创建一个该模型的实例
- 调用模型方法以执行任何必需的数据库更新
- 确定哪个视图应该用于向用户呈现网页,并创建一个该视图的实例,或者
- 如果用户应该收到重定向到另一个 URL,那么确定该重定向 URL。
查看
MVC 视图功能被分成 2 个文件
- 视图类文件,通常仅称为视图,在此之后,我们将只称其为视图
- tmpl 文件
该视图指定将显示在即将显示的网页上应显示的内容,并整理输出 HTTP 响应所需的所有数据。
在控制器创建视图实例之后,它调用视图的 setModel()
方法并传递模型实例。通过这种方式,视图知道使用哪个模型,并调用模型的方法来获取返回给用户所需的数据。此数据存储在视图的实例变量中。
tmpl 文件(有时称为模板或布局文件——Joomla 在这里并非完全一致!)负责输出要显示的网页的实际 HTML。视图本身不会输出 HTML,而是将此委托给 tmpl 文件。
tmpl 包含在视图上下文中运行的 PHP 代码。视图类通常扩展 Joomla\CMS\MVC\View\HtmlView,并且该类的 display()
方法找出要使用的 tmpl 然后执行文件的 include
。
这意味着,如果视图将响应数据保存在例如 $this->items
中,那么 tmpl 文件在输出 HTML 时可以访问相同的 $this->items
。
这样分离视图和 tmpl 能够实现另一种级别的灵活性,因为您可以轻松地设置布局覆盖,以使用您自己首选的 HTML 输出视图数据。
模型
模型封装了组件使用的数据。在大多数情况下,此数据来自数据库,可能是 Joomla 数据库或某些外部数据库,但模型也有可能从其他来源获取数据,例如运行在另一台服务器上的 Web 服务 API。模型还负责在适当的情况下更新数据库。模型的目的是将控制器和视图与获取或修改数据的方式的详细信息隔离。
如果组件正在显示 Joomla 表单方法通过 XML 定义的表单,Model 会处理 Form
实例的设置和配置,以便 tmpl 使用 $form->renderField()
等输出字段。
表
如果你的扩展程序有一个或多个数据库表,则你应该为每个数据库表创建一个 Table 类。你的 Table 类将继承自 Joomla 库 Table 类,该类提供对基础数据库表的 CRUD(创建/读取/更新/删除)访问。
Table 类仅提供对单个记录的访问,所以如果需要对单个记录执行 CRUD 操作(例如在数据库中创建或更新记录),则 Model 会使用该类。
如果相反需要访问数据库表中的多个记录,则 Model 将直接访问数据库,而不是使用 Table 类。
HTTP 请求任务参数
Joomla 使用 HTTP 请求任务参数来确定应该使用哪个控制器。任务参数可以在 HTTP GET 或 HTTP POST 中发送 - Joomla 不关心哪个 - 而且它只是一个普通 HTTP 参数,没什么特别的。
任务参数的格式为 <controllerType>.<method>
。第一部分标识要使用的特定 Controller 类,第二部分标识要调用的该类的实例方法。
控制器类型可能不存在,在这种情况下将使用 DisplayController 类。
如果根本没有设置任务参数,则 DisplayController 类中的 display()
方法会运行。
稍后我们将看一些示例。
你的 Joomla 内的 MVC
当然,你的组件的 MVC 代码在 Joomla 的库代码的上下文中运行,就像三明治中的肉一样。当 Joomla 确定应该运行你的组件时,它会获取你的组件的 Extension 和 Dispatcher 类,而实际分析任务参数来确定要实例化哪个 Controller 类的正是 Joomla ComponentDispatcher 类的 dispatch()
函数,如Extension and Dispatcher 类中所述。然后 dispatch()
调用组件的 execute()
方法,传递任务参数的 <method>
部分。假定你的组件在继承链中有 Joomla\CMS\MVC\Controller\BaseController,那么在这种情况下(正常情况下),你的 Controller 的 method
函数将会被调用。
execute()
方法完成后 dispatch()
方法将调用控制器的 redirect()
方法 - 我们稍后会看到这个的意义何在。
另一方面,由 tmpl 文件输出的 HTML 不会直接进入 HTTP 响应,而是使用 PHP 输出缓冲区 由 Joomla 捕获到一个缓冲区中,稍后注入最终的 HTML 页面,外加任何模块、消息等需要包含在网页中的内容。