MVC 工厂概述
MVC 工厂类用于在 Joomla 中创建组件控制器、视图、模型和表格类的实例。
每个组件都有自己的 MVCFactory 类实例,该实例在传递组件的命名空间前缀时被实例化。
它具有用于创建每个类的函数:createController
、createView
、createModel
、createTable
,并且在其最简单的形式中,您可以将以下内容传递到每个函数中
name
- 例如“display”、“article”等prefix
- “site”或“administrator”。
(您可以使用大写或小写字母指定name
和prefix
- Joomla 将为您将第一个字母大写)。
然后,MVCFactory 类函数将生成要实例化的类的名称,并尝试实例化它。
例如,如果您的组件是com_example
,命名空间前缀为 \Mycompany\Component\Example,那么在您的控制器类中,您可以使用(其中$this->factory
指向您的 MVCFactory 实例)
$model = $this->factory->createModel('Example', 'Administrator');
MVCFactory 函数将尝试实例化 \Mycompany\Component\Example\Administrator\Model\ExampleModel。
事实上,库 MVC BaseController 类使它变得更加简单,您只需要调用
$model = $this->getModel('example', 'administrator');
请注意,如果您的组件在前端(网站)运行,您仍然可以使用管理员模型,如果它在后端(管理员)运行,您仍然可以使用网站模型。没有限制。
创建 MVCFactory 类实例
您的组件的 MVCFactory 通过在您的 services/provider.php 文件中将其定义为依赖项来创建,如依赖项注入中所述,但您不必了解 Joomla 依赖项注入的所有复杂性即可有效地使用它。
创建您的控制器类实例
如扩展和调度程序类中所述,您的控制器类在 ComponentDispatcher 类的dispatch
函数中实例化。它有一个指向 MVCFactory 类的实例变量,并将调用
$controller = $this->mvcFactory->createController($name, $client, ..);
传递来自task参数的第一部分的$name
(如果不存在task参数,则为“display”),以及根据此操作是在前端还是后端运行而将$client
设置为“site”或“administrator”。
在此图(以及下一个图)中
- “工厂”类为蓝色,普通 MVC 类为黄色。
- 虚线表示一个类具有一个指向另一个类实例的实例变量
- 实线表示方法调用
- 粗实线表示工厂类实例化类的位置
创建您的视图、模型和表格类实例
使用 Joomla MVC 工厂范例
- 控制器负责实例化视图和模型,并且可以调用
getView
和getModel
来执行此操作 - 模型负责实例化表格,并且可以调用
getTable
来执行此操作
视图也可以通过getModel
调用获取模型,但前提是控制器已通过首先获取模型实例并将此实例传递到视图中来设置此操作
$view->setModel($model);
视图、模型和表格类的默认名称
虽然控制器的名称取自task参数,但视图、模型和表格类的默认名称取自view参数。如果您只是调用getView()
、getModel()
和getTable()
而不带任何参数,这些默认类将被实例化。
因此,例如,对于具有 URL 查询“?option=com_example&view=viewname”且没有task参数的请求创建的类的名称将是
<namespace>\Controller\DisplayController
<namespace>\View\Viewname\HtmlView
<namespace>\Model\ViewnameModel
<namespace>\Table\ViewnameTable
总结
在本节中,我们已经介绍了很多背景知识,以帮助您了解事物的工作原理,但这一切都是为了简化您在 MVC 类中的操作。
在您的控制器中,您可以创建视图和模型,并向视图提供对模型的引用
$model = $this->getModel(); // to get the default Model, based on the view= parameter
$foomodel = $this->getModel('foo'); // to get the Model\FooModel
$view = $this->getView(); // to get the default View, based on the view= parameter
$fooview = $this->getView('foo'); // to get the View\Foo\HtmlView
$view->setModel($model, true); // to set the view's default model, accessible inside the view by $this->getModel()
$view->setModel($foomodel); // make the $foomodel accessible to the view by $this->getModel('foo')
要获取多个模型,只需将每个名称传递给getModel
$foomodel = $this->getModel('foo');
$barmodel = $this->getModel('bar');
如果您的组件在前端运行,但您想获取其管理员模型,只需传递$prefix
第二个参数
$model = $this->getModel('foo', 'administrator');
在您的视图中,您可以访问控制器设置的模型
$model = $this->getModel(); // to get the default model
$foomodel = $this->getModel('foo'); // to get the foo model
在您的模型中,您可以创建表格
$table = $this->getTable(); // if your Table class matches the view= parameter in the HTTP request
$table = $this->getTable('example'); // to get the ExampleTable class
问题
引入 MVCFactory 类的一个关键原因是删除使用static::getInstance()
调用来获取 MVC 类实例之一的操作。但是,您可能会发现该方法存在一两个问题。
例如,当在表格类中保存数据库记录(例如在Joomla\CMS\Table\Content::store()
中)时,Joomla 获取该表格类的另一个实例以验证即将保存的别名是否唯一。但是,当创建表格实例时,不会向其传递指向 MVCFactory 实例的指针,因此它无法使用 MVCFactory 的createTable
函数创建另一个实例。在 Joomla 4 中,解决方案是使用已弃用的getInstance()
函数
$table = Table::getInstance('Content', 'JTable', ['dbo' => $this->getDbo()]);
在 Joomla 5 中,它只是创建了自己的新版本
$table = new self($this->getDbo(), $this->getDispatcher());
因此,您可以使用类似的方法来避免使用已弃用的getInstance
方法(或直接在您的数据库表上执行 SQL 查询)。