当前位置: 技术文章>> 一篇文章详解magento2中的路由,路由定义,路由规则

文章标题:一篇文章详解magento2中的路由,路由定义,路由规则
  • 文章分类: Magento
  • 20608 阅读
系统学习magento二次开发,推荐小册:《Magento中文全栈二次开发 》

本小册面向Magento2以上版本,书代码及示例兼容magento2.0-2.4版本。涵盖了magento前端开发,后端开发,magento2主题,magento2重写,magento2 layout,magento2控制器,magento2 block等相关内容,带领您成为magento开发技术专家。


我们可以说Magento中的路由是最重要的部分之一。完整的应用程序(Magento 2)流程取决于处理URL请求和负责匹配和处理该请求的路由器类。本文介绍了Magento 2中的路由器流,并分析了默认安装附带的一些路由器。还将展示如何创建一个自定义路由器。将提到路由器如何匹配操作(控制器类),有关控制器的详细信息将在单独的文章中介绍。

### 路由流

首先,我们需要分析完整的路由流程,以便稍后可以更详细地了解每个部分。正如我们已经知道的,Magento 2创建了HTTP应用程序,其中类(启动方法)请求流将在其中启动。我们的流程从创建前端控制器开始:

$frontController = $this->_objectManager->get('Magento\Framework\App\FrontControllerInterface');

前端控制器负责遍历所有可用的路由器,并为当前请求匹配负责的路由器。稍后我们将详细介绍前端控制器。现在,要了解完整的流程,了解应用程序如何匹配路由器非常重要。路由器列表是在位于Magento\Framework\App的RouterList类中创建的(在Front Controller中调用用于在路由器上循环),该类负责路由器列表的排序和迭代。如果路由器负责当前请求,则路由器类负责匹配。让我们来看看Magento 2流程:

index.php(运行引导程序并创建HTTP应用程序)→HTTP应用程序→FrontController →路由→控制器处理→等

现在,我们将分析路由流的每个部分,以便更好地了解Magento 2中的路由。

### 前端控制器

与Magento 1相同,这是在HTTP应用程序启动(启动方法)时调用的入口路由点。它负责匹配负责当前请求的路由器。它位于lib/internal/Magento/Framework/App/FrontController.php下。你可以看到在HTTP启动方法中使用了FrontControllerInterface。让我们在代码中看一下:

class Http implements \Magento\Framework\AppInterface
{
    public function launch()
    {
        ...
            //Here Application is calling front controller and it's dispatch method
        $frontController = $this->_objectManager->get('Magento\Framework\App\FrontControllerInterface');
        $result = $frontController->dispatch($this->_request);
        ...
    }
}

现在,当我们知道如何以及何时调用前端控制器时,让我们看一下前端控制器类和调度方法本身:

lib/internal/Magento/Framework/App/FrontController.php

class FrontController implements FrontControllerInterface
{
    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);
                        $actionInstance->getResponse()->setNoCacheHeaders();
                        $result = $actionInstance->dispatch($request);
                        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;
    }
}

正如我们所看到的,调度方法将遍历所有路由器(启用,我们稍后将在路由器配置中介绍这一点),直到一个路由器匹配并调度请求($request→setDispatched(true);)或工艺路线周期计数器超过 100。路由器可以匹配,但是如果没有调度,它将重复环路槽路由器(向前操作)。此外,路由器可以重定向和调度,也可以匹配和处理。路由器列表类在请求流中解释。现在,我们可以继续查看路由器匹配(匹配方法)的工作原理以及路由器到底是什么。

### 路由器

简而言之,路由器是负责匹配和处理URL请求的PHP类。默认情况下,Magento框架和Magento核心中有一些路由器;Base、DefaultRouter、CMS 和 UrlRewrite。我们将涵盖所有这些内容,解释它们的目的以及它们的工作原理。路由器正在实现路由器接口。现在,让我们看一下默认路由器的流程:

基本路由器→ CMS 路由器→ url重写路由器→默认路由器

(这是路由器循环 – FrontController::d ispatch())

### 基础路由器

它位于lib/internal/Magento/Framework/App/Router/Base.php,它是循环中的第一个,如果你是Magento 1开发人员,你知道它是标准路由器。匹配方法将解析请求和匹配操作,在第二种方法中,它将设置模块前端名称、控制器路径名、操作名称、控制器模块和路由名称。在基本路由器上,标准Magento URL(前端名称/操作路径/操作/参数1/等参数/)匹配。

### 内容管理系统路由器

CMS路由器位于app/code/Magento/Cms/Controller/Router.php中,用于处理CMS页面,它将模块名称(模块前端名称)设置为“cms”,控制器名称(控制器路径名称)设置为“页面”,操作名称设置为“view” – app/code/Magento/Cms/Controller/Page/View.php控制器。设置基本控制器的格式后,它将设置页面 ID 并转发它,但不会调度它。转发意味着它将中断当前的路由器环路并再次启动环路(它最多可以这样做 100 次)。该路由器环路将匹配基本路由器,该路由器将在 Cms/控制器/页面中激活视图控制器并显示保存的页面 ID(根据 url 找到的页面 ID)。

### 网址重写路由器

在Magento 2中,UrlRewrite有自己的路由器,如果你熟悉Magento 1,那么你就会知道Url Rewrite是标准路由器的一部分。它位于:app/code/Magento/UrlRewrite/Controller/Router.php它使用Url Finder来获取与数据库中的URL匹配的url重写:

$rewrite = $this->urlFinder->findOneByData(
                    [
                        UrlRewrite::ENTITY_TYPE => $oldRewrite->getEntityType(),
                        UrlRewrite::ENTITY_ID => $oldRewrite->getEntityId(),
                        UrlRewrite::STORE_ID => $this->storeManager->getStore()->getId(),
                        UrlRewrite::IS_AUTOGENERATED => 1,
                    ]
                );

它将像 CMS 路由器一样转发动作。

### 默认路由器

它位于lib/internal/Magento/Framework/App/Router/DefaultRouter中.php它是路由器循环中的最后一个。当所有其他路由器不匹配时,使用它。在Magento 2中,我们可以为“未找到”页面创建自定义句柄以显示自定义内容。以下是 DefaultRouter 中没有路由处理程序列表的循环:

foreach ($this->noRouteHandlerList->getHandlers() as $noRouteHandler) {
            if ($noRouteHandler->process($request)) {
                break;
            }
        }

### 自定义路由器(带示例)

前端控制器将遍历 routersList 中的所有路由器(从 routes.xml 中的配置创建),因此我们需要通过在 di.xml 模块中添加我们对新路由器的配置,在 lib/internal/Magento/Framework/App/RouterList 中添加自定义路由器.php。我们将创建一个新模块(我们称之为Inchoo/CustomRouter),然后我们将在routersList中添加新的路由器,最后,创建路由器类。

自定义路由器只是一个示例,您可以在其中了解如何匹配和转发要匹配的基本路由器的请求。首先,我们需要为位于app/code/Inchoo/CustomRouter中的模块创建文件夹结构,然后我们将在etc文件夹中创建模块.xml并在模块根目录中创建composer.json,其中包含模块信息。现在,我们可以通过在 etc/前端文件夹中向 di.xml 添加配置来创建自定义路由器,因为我们只想为前端提供自定义路由器。最后,我们将在控制器文件夹中创建路由器.php,其中包含用于匹配路由器的逻辑。我们将搜索 URL 并检查 URL 中是否有特定单词,然后,根据该单词,我们将设置模块前端名称、控制器路径名称、操作名称,然后转发基本控制器的请求。我们将搜索两个词:“examplerouter”和“exampletocms”。在“examplerouter”匹配中,我们将转发到基本路由器匹配格式(通过将模块前端名称设置为“inchootest”,控制器路径名称设置为“test”,操作名称设置为“test”),在“exampletocms”上,我们将转发到基本路由器以显示“关于我们”页面。

di.xml(位于 etc/前端)

<?xml version="1.0"?>
<!--
/**
 * Copyright © 2015 Inchoo d.o.o.
 * created by Zoran Salamun(zoran.salamun@inchoo.net)
 * Module is created for Custom Router demonstration
 */
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
    <type name="Magento\Framework\App\RouterList">
        <arguments>
            <argument name="routerList" xsi:type="array">
                <item name="inchoocustomrouter" xsi:type="array">
                    <item name="class" xsi:type="string">Inchoo\CustomRouter\Controller\Router</item>
                    <item name="disable" xsi:type="boolean">false</item>
                    <item name="sortOrder" xsi:type="string">22</item>
                </item>
            </argument>
        </arguments>
    </type>
</config>
<?php
namespace Inchoo\CustomRouter\Controller;
 
/**
 * Inchoo Custom router Controller Router
 *
 * @author      Zoran Salamun <zoran.salamun@inchoo.net>
 */
class Router implements \Magento\Framework\App\RouterInterface
{
    /**
     * @var \Magento\Framework\App\ActionFactory
     */
    protected $actionFactory;
 
    /**
     * Response
     *
     * @var \Magento\Framework\App\ResponseInterface
     */
    protected $_response;
 
    /**
     * @param \Magento\Framework\App\ActionFactory $actionFactory
     * @param \Magento\Framework\App\ResponseInterface $response
     */
    public function __construct(
        \Magento\Framework\App\ActionFactory $actionFactory,
        \Magento\Framework\App\ResponseInterface $response
    ) {
        $this->actionFactory = $actionFactory;
        $this->_response = $response;
    }
 
    /**
     * Validate and Match
     *
     * @param \Magento\Framework\App\RequestInterface $request
     * @return bool
     */
    public function match(\Magento\Framework\App\RequestInterface $request)
    {
        /*
         * We will search “examplerouter” and “exampletocms” words and make forward depend on word
         * -examplerouter will forward to base router to match inchootest front name, test controller path and test controller class
         * -exampletocms will set front name to cms, controller path to page and action to view
         */
        $identifier = trim($request->getPathInfo(), '/');
        if(strpos($identifier, 'exampletocms') !== false) {
            /*
             * We must set module, controller path and action name + we will set page id 5 witch is about us page on
             * default magento 2 installation with sample data.
             */
            $request->setModuleName('cms')->setControllerName('page')->setActionName('view')->setParam('page_id', 5);
        } else if(strpos($identifier, 'examplerouter') !== false) {
            /*
             * We must set module, controller path and action name for our controller class(Controller/Test/Test.php)
             */
            $request->setModuleName('inchootest')->setControllerName('test')->setActionName('test');
        } else {
            //There is no match
            return;
        }
 
        /*
         * We have match and now we will forward action
         */
        return $this->actionFactory->create(
            'Magento\Framework\App\Action\Forward',
            ['request' => $request]
        );
    }
}

routes.xml (located in etc/frontend)

<?xml version="1.0"?>
 
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/App/etc/routes.xsd">
    <router id="standard">
        <route id="inchootest" frontName="inchootest">
            <module name="Inchoo_CustomRouter" />
        </route>
    </router>
</config>


Test.php (test controller action class)


<?php
/**
 * Copyright © 2015 Inchoo d.o.o.
 * created by Zoran Salamun(zoran.salamun@inchoo.net)
 */
namespace Inchoo\CustomRouter\Controller\Test;
 
class Test extends \Magento\Framework\App\Action\Action
{
    /**
     * Listing all images in gallery
     *  -@param gallery id
     */
    public function execute()
    {
        die("Inchoo\\CustomRouter\\Controller\\Test\\Test controller execute()");
    }
}


您可以在以下位置查看示例模块:

https://github.com/zoransalamun/magento2-custom-router

安装:

首先将存储库添加到作曲家配置:

composer config repositories.inchoocustomrouter vcs git@github.com:zoransalamun/magento2-custom-router.git

需要带有作曲家的新包:

composer require inchoo/custom-router:dev-master

启用 Inchoo 自定义路由器模块

php bin/magento module:enable Inchoo_CustomRouter

刷新所有内容:

php bin/magento setup:upgrade


推荐文章