Routing 为 Magento 2 一个重要的部分,本文介绍基本应用
Routing 为 Magento 2 一个重要的部分,本文介绍基本应用
Magento 2请求的流程
在Magento 2中,请求URL将如下所示:
http://example.com/index.php/front_name/controller/action
在该URL中,您将看到将用于查找模块的front_name。路由器通过在routes.xml中定义为每个模块定义此名称,我们将在下面看到更多细节。
当您在Magento 2中发出请求时,它将按照此流程查找 controller/action
: index.php → HTTP app → FrontController → Routing → Controller processing → etc
该FrontController
会在HTTP中类中调用路由信息,会发现该请求controller/action
匹配。
文件: vendor/magento/framework/App/FrontController.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 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()
方法中所看到的,路由器列表将循环以查找与此请求匹配的路由器列表。如果它找到该请求的控制器操作,则将调用并执行该操作。
在frontend/adminhtml上创建自定义路由
在这部分中,我们将使用一个简单的模块Mageplaza_HelloWorld。请按照上一篇文章了解如何在Magento 2中创建和注册模块。
我们将找到如何创建前端路由,管理路由以及如何使用路由重写控制器。
frontend路由
要注册前端路由,我们必须创建一个routes.xml文件:
文件: app/code/Mageplaza/HelloWorld/etc/frontend/routes.xml
1 2 3 4 5 6 7 8 9 10 11 | <? 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 frontName="helloworld" id="helloworld"> <!--The module which this route match to--> < module name="Mageplaza_HelloWorld"/> </ route > </ router > </ config > |
请查看代码,您将看到注册路由非常简单。您必须使用标准路由器作为前端。此路由将有一个子节点,为其定义模块和2个属性:
- id属性是一个唯一的字符串,用于标识此路由。您将使用此字符串声明此模块操作的布局句柄
- frontName属性也是一个唯一的字符串,它将显示在url请求中。例如,如果您声明这样的路线:
<route frontName="helloworld" id="helloworld">
该模块的URL应该是:
http://example.com/index.php/helloworld/controller/action
此操作的布局句柄是:helloworld_controller_action.xml
因此,使用此示例路径,您必须在此文件夹中创建操作类:{namespace}/{module}/Controller/{Controller}/{Action}.php
adminhtml 路由
此路由与前端路由相同,但您必须在adminhtml文件夹中将其声明为路由器ID为admin
。
文件: app/code/Mageplaza/HelloWorld/etc/adminhtml/routes.xml
1 2 3 4 5 6 7 8 9 10 11 | <? 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 'admin' for admin route --> < router id="admin"> <!--Define a custom route with id and frontName --> < route id="mageplaza_helloworld" frontName="mageplaza_helloworld"> <!--The module which this route match to--> < module name="Mageplaza_HelloWorld"/> </ route > </ router > </ config > |
管理页面的url与前端页面的结构相同,但是admin_area
之前会添加名称route_frontName
以识别这是一个管理路由器。例如,admin cms页面的url:
http://example.com/index.php/admin/mageplaza_helloworld/controller/action
管理页面的控制器操作将添加到文件夹内Controller/Adminhtml
。例如,对于以上网址:
1 | {namespace}/{module}/Controller/Adminhtml/{Controller}/{Action}.php |
使用route重写控制器
在这条路径中,我们将看到如何用路由器重写控制器。如上面的路径,您可以看到每个路由都有一个id属性来识别。那么如果我们定义具有相同id属性的2路由会发生什么?
答案是控制器操作将在两个模块中找到。Magento系统在配置模块排序顺序之前/之后提供属性,该顺序定义了首先找到的模块控制器。这是控制器重写的逻辑。
例如,如果我们想重写控制器customer / account / login,我们将在route.xml中定义更多路由,如下所示:
文件: app/code/Mageplaza/HelloWorld/etc/frontend/routes.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <? 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 frontName="helloworld" id="helloworld"> <!--The module which this route match to--> < module name="Mageplaza_HelloWorld"/> </ route > < route id="customer"> < module name="Mageplaza_HelloWorld" before="Magento_Customer" /> </ route > </ router > </ config > |
和控制器文件: app/code/Mageplaza/HelloWorld/Controller/Account/Login.php
所以frontController首先在我们的模块中找到Login动作,如果找到它,它将运行并且不会运行Magento_Customer的Login动作。我们成功地重写了一个控制器。
您也可以使用它来使第二个模块与另一个模块具有相同的路由器。例如,通过上述声明,您可以使用路由'customer'作为控制器操作。如果您有控制器'博客'和操作'Index.php',您可以使用此网址:
http://example.com/customer/blog/index
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 趁着过年的时候手搓了一个低代码框架
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!