Magento2路由Route详解[教程]

如果您想阅读完整的教程请查看[Magento2模块开发中文教程索引]
(Magento2模块开发中文教程索引).

在本文中,我们将讨论Magento 2非常重要的一个部分,路由。路由将定义模块的名称,我们可以在url中使用该模块来查找模块并执行控制器操作。
##Magento 2 URL请求流
在Magento,URL格式看起来会是这样的:

example.com/index.php/front_name/controller/action

在该url中,您将看到用于查找模块的 front_name,路由为每个模块定义这个名称。我们将会看到更多的细节。
当你向Magento2发送请求时,它会跟随这个流程来查找:

controller/action: index.php → HTTP app → FrontController → Routing → Controller processing → etc

FrontController 将在Http类中调用,该路由请求将找到 **“controller/action”**进行匹配。
文件:

vendor/magento/framework/App/FrontController.php

内容:

public function dispatch(RequestInterface $request)
{
\Magento\Framework\Profiler::start('routers_match');
$routingCycleCounter = 0;
$result = null;
while (!$request->isDispatched() && $routingCycleCounter++ < 100) {
   /** @var \Magento\Framework\App\RouterInterface $router */
   foreach ($this->_routerList as $router) {
       try {
           $actionInstance = $router->match($request);
           if ($actionInstance) {
               $request->setDispatched(true);
               $this->response->setNoCacheHeaders();
               if ($actionInstance instanceof \Magento\Framework\App\Action\AbstractAction) {
                   $result = $actionInstance->dispatch($request);
               } else {
                   $result = $actionInstance->execute();
               }
               break;
           }
       } catch (\Magento\Framework\Exception\NotFoundException $e) {
           $request->initForward();
           $request->setActionName('noroute');
           $request->setDispatched(false);
           break;
       }
   }
}
 \Magento\Framework\Profiler::stop('routers_match');
if ($routingCycleCounter > 100) {
   throw new \LogicException('Front controller reached 100 router match iterations');
}
return $result;
}

正如您在这个 **dispatch()**方法中看到的,路由器列表将会被循环,以找到符合这个请求的匹配项。如果它找到该请求的控制器操作,将调用并执行该操作。
##在前台或者后台创建自定义路由
在这一部分中,我们将使用一个简单的Magentochina_HelloWorld模块。请依照前一篇文章了解如何在Magento 2中创建和注册一个模块

我们将会学会如何创建前端路由、管理路由以及如何使用路由来重写控制器

###前台路由
要注册一个前台路由,我们要首先创建一个 routes.xml文件

app/code/Mageplaza/HelloWorld/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">
<!--Use router 'standard' for frontend route-->
<router id="standard">
   <!--Define a custom route with id and frontName-->
   <route id="example" frontName="example">
       <!--The module which this route match to-->
       <module name="Magentochina_HelloWorld" />
   </route>
</router>
</config>

请查看代码,您将看到注册前台路由非常简单。您必须使用前台的标准路由。这路由将有一个子标签定义它的模块和两个属性:

  • id属性是唯一标识字符串,它将识别这个路由。您将使用此字符串来声明此模块操作的layout handle
  • frontName属性也是唯一标识字符串,它将显示在url请求中。例如,如果你声明一条这样的路由:
<route id="exampleid" frontName="examplefront">

该模块的url应该是:

example.com/index.php/examplefront/controller/action

这个action的布局句柄( layout handle )是:exampleid_controller_action.xml于这个路由,所以你必须在该文件夹中创建action类: {module_path}/Controller/Controller/Action.php

###后台路由
后台路由与前台路由相同,但您必须在带有路由器id的adminhtml文件夹中声明它。
文件:

app/code/Magentochina/HelloWorld/etc/adminhtml/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">
<!--Use router 'standard' for frontend route-->
<router id="admin">
   <!--Define a custom route with id and frontName-->
   <route id="example" frontName="example">
       <!--The module which this route match to-->
       <module name="Magentochina_HelloWorld"/>
   </route>
</router>
</config>

后台页面的url与前台页面的结构相同,但是需要在 route_frontName之前添加 admin_area名称以识别这是一个后台路由。例如,后台cms页面的url:

example.com/index.php/admin/example/blog/index

后台页面的控制器action将添加到Controller/Adminhtml文件夹中.例如上面的url:

{module_path}/Controller/Adminhtml/Blog/Index.php

###使用路由重写控制器

在这小节中,我们将看到如何用路由器重写控制器。在上面的小节中,您可以看到每个路由都有一个id属性来标识。那么,如果我们用相同的id属性来定义两条路由会发生什么呢?

答案是在两个模块中都将发现控制器action。Magento系统提供了在配置模块排序 before/after 的属性,它定义了首先要找到的模块控制器。这是控制器重写的逻辑。

例如,如果我们想重写 customer/account/login,我们将在路由中定义更多的 route.xml ,像是这样的:
文件:

app/code/Magentochina/HelloWorld/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">
<!--使用'standard'于前台路由-->
<router id="standard">
   <!--定义自定义路由的ID和frontName-->
   <route id="example" frontName="example">
       <!--路由匹配的模块-->
       <module name="Magentochina_HelloWorld" />
   </route>
   <route id="customer">
       <module name="Magentochina_HelloWorld" before="Magento_Customer" />
   </route>
</router>
</config>

还有控制器文件:

app/code/Magnetochina/HelloWorld/Controller/Account/Login.php

因此,frontController将首先在我们的模块中找到登录action,如果找到它,它将运行. Magento_Customer的登录action将不会运行。我们成功地重写了一个控制器。

您还可以使用这个程序来拥有第二个模块,该模块与另一个模块具有相同的路由器。例如,在上面声明的情况下,您可以为控制器action使用路由’ customer '。如果你有控制器 **‘blog’**和 ‘Index.php’。你可以使用这个url:

example.com/customer/blog/index

####本教程翻译自mageplaza,如果你想查看完整的教程,请点击这里.译者:西帅
####如果觉得本站翻译得内容对您有帮助,又没有时间帮助翻译回馈社区.请打赏我们,您的支持是我们的动力:

####转载说明:非常欢迎转载,但是必须保证文章的完整性并附上原文地址和翻译原文的地址,保证阅读者不会产生歧义.