本篇围绕 Magento 2 的 Controller ,介绍控制器是怎么工作的,怎么创建,它和 layout 配置文件配合,怎么输出一个页面,以及控制器中经常用到的两个方法 _redirect()
和 _forward()
。
控制器在 Magento 2 中是很重要的,一般而言,对 PHP MVC 框架来说也是很重要的。它的功能是接受请求,处理请求和呈现页面(render page)。
模块的 Controller 目录下有一个或多个文件,每个文件都是一个单独的 class ,每个 class 都有一个 execute
方法。Magento 2 中有两种类型的控制器,一种是前台控制器,另一种是后台控制器。他们大体上是一样的流程,后台控制器稍微特别点,它拥有一个检查权限的方法。
控制器怎么工作的?
它从终端用户(浏览器或命令行)接受请求,比如:
http://example.com/route_name/controller/action
route_name
是一个在 routes.xml 中设置的唯一名称controller
是 Controller 目录下的文件夹action
是一个有 execute 方法的 class
Magento 2 系统中处理请求,路由到对应控制器的类是 frontController (Magento\Framework\App\FrontController
)
看代码:
foreach ($this->_routerList as $router) {
try {
$actionInstance = $router->match($request);
…
}
如果找到匹配的 action 类,那么就会执行其中的 execute
方法。
如何创建控制器
如果还不清楚怎么创建模块,请参考 创建 Magento 2 Hello World Simple Module。本篇以该文中创建的模块为基础。该文末尾可以找到对应的代码下载地址,可以下载后跟着本文的步骤做。本文末尾也附带完成后的代码供比对。
要创建控制器,首先需要在模块目录下创建 Controller
目录。
假设我们在 ThankIT_HelloWorld
模块的基础上创建一个 Index
controller 和一个 Index
action
创建 routes.xml
File: etc/frontend/routes.xml
<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
<router id="standard">
<route frontName="helloworld" id="helloworld">
<module name="ThankIT_HelloWorld"/>
</route>
</router>
</config>
创建控制器
File: Controller/Index/Index.php
<?php
namespace ThankIT\HelloWorld\Controller\Index;
class Index extends \Magento\Framework\App\Action\Action {
protected $resultPageFactory;
/**
* Constructor
*
* @param \Magento\Framework\App\Action\Context $context
* @param \Magento\Framework\View\Result\PageFactory $resultPageFactory
*/
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Magento\Framework\View\Result\PageFactory $resultPageFactory
)
{
$this->resultPageFactory = $resultPageFactory;
parent::__construct($context);
}
/**
* Execute view action
*
* @return \Magento\Framework\Controller\ResultInterface
*/
public function execute()
{
return $this->resultPageFactory->create();
}
}
所有 controller 都必须继承自 \Magento\Framework\App\Action\Action
该类有 dispatch
方法,就是 dispatch
方法会调用 execute
方法。在 execute
方法中我们放控制器的逻辑并返回响应结果。
创建 layout 文件
File: view/frontend/layout/helloworld_index_index.xml
<?xml version="1.0" ?>
<page layout="1column" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="content">
<block class="ThankIT\HelloWorld\Block\Index\Index" name="index.index" template="ThankIT_HelloWorld::index/index.phtml"/>
</referenceContainer>
</body>
</page>
创建 Block
File: app\code\ThankIT\HelloWorld\Block\Index\Index.php
<?php
namespace ThankIT\HelloWorld\Block\Index;
use Magento\Framework\View\Element\Template;
class Index extends Template
{
}
创建 template
File: view/frontend/templates/index/index.phtml
Welcome to hellomagento2.com
刷新缓存
命令行:
php bin/magento cache:flush
测试
浏览器中打开http://<yourhost.com>/helloworld/index/index
或者 http://<yourhost.com>/helloworld/
我们就可以看到结果了,这次不是纯字符串哦。
Permission – ACL
参考 Magento 2 Admin ACL Access Control Lists
Magento 2 控制的其他方法
Forward method
_forward()
protected 方法会将请求转向其他 controller/action
但是用户在浏览器中看到的 URL 是不变的。
例如:
File: Controller/Index/Forward.php
<?php
namespace ThankIT\HelloWorld\Controller\Index;
class Forward extends \Magento\Framework\App\Action\Action
{
public function execute()
{
$this->_forward('index');
}
}
创建好以后 cache:flush
然后访问 http://<yourhost.com>/helloworld/index/forward
会看到和访问 http://<yourhost.com>/helloworld/index/index
一样的结果,但是我们的 url 并没有改变。
_forward()
还有其他参数:
function _forward($action, $controller = null, $module = null, array $params = null)
其中的 $module
指的是 route_name 对应在 routes.xml 中设置的唯一名称。
Redirect method
_redirect()
除了会会将请求转向其他 controller/action
,响应的 URL 也会发生改变。
可将上述例子中的 $this->_forward('index');
改成 $this->_redirect('*/*/index');
查看效果。
参考文档
how to create Controllers in Magento 2