Вопрос

I am trying to redirect the page/action by using a custom router as Router.php, but I am getting 100 router match iterations exception.

app\code\Custom\Module\etc\frontend\di.xml

<?xml version="1.0"?>
<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="Custom_Module" xsi:type="array">
                    <item name="class" xsi:type="string">Custom\Module\Controller\Router</item>
                    <item name="disable" xsi:type="boolean">false</item>
                    <item name="sortOrder" xsi:type="string">22</item>
                </item>
            </argument>
        </arguments>
    </type>
    <virtualType name="CustomModuleRoutingEntityPosts" type="Custom\Module\Model\Routing\Entity">
        <arguments>
            <argument name="prefixConfigPath" xsi:type="const">Custom\Module\Model\Posts\Url::URL_PREFIX_CONFIG_PATH</argument>
            <argument name="suffixConfigPath" xsi:type="const">Custom\Module\Model\Posts\Url::URL_SUFFIX_CONFIG_PATH</argument>
            <argument name="factory" xsi:type="object">Custom\Module\Model\PostsFactory</argument>
            <argument name="controller" xsi:type="string">posts</argument>
        </arguments>
    </virtualType>
    <type name="Custom\Module\Controller\Router">
        <arguments>
            <argument name="routingEntities" xsi:type="array">
                <item name="posts" xsi:type="object">CustomModuleRoutingEntityPosts</item>
            </argument>
        </arguments>
    </type>
</config>

app\code\Custom\Module\Controller\Router.php

http://localhost/magento2/posts/reply/

namespace Custom\Module\Controller;

use Magento\Framework\App\ActionFactory;
use Magento\Framework\App\Action\Forward;
use Magento\Framework\App\Action\Redirect;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\App\ResponseInterface;
use Magento\Framework\App\RouterInterface;
use Magento\Framework\App\State;
use Magento\Framework\DataObject;
use Magento\Framework\Event\ManagerInterface;
use Magento\Framework\Url;
use Magento\Framework\UrlInterface;
use Magento\Store\Model\ScopeInterface;
use Magento\Store\Model\StoreManagerInterface;
use Custom\Module\Model\Routing\Entity;
use Magento\Framework\Controller\ResultFactory;

class Router implements RouterInterface {

    /**
     * @var \Magento\Framework\App\ActionFactory
     */
    protected $actionFactory;

    /**
     * Event manager
     * @var \Magento\Framework\Event\ManagerInterface
     */
    protected $eventManager;

    /**
     * Store manager
     * @var \Magento\Store\Model\StoreManagerInterface
     */
    protected $storeManager;

    /**
     * Posts factory
     * @var \Custom\Module\Model\PostsFactory
     */
    protected $postsFactory;

    /**
     * Config primary
     * @var \Magento\Framework\App\State
     */
    protected $appState;

    /**
     * Url
     * @var \Magento\Framework\UrlInterface
     */
    protected $url;

    /**
     * Response
     * @var \Magento\Framework\App\ResponseInterface|\Magento\Framework\App\Response\Http
     */
    protected $response;

    /**
     * @var \Magento\Framework\App\Config\ScopeConfigInterface
     */
    protected $scopeConfig;

    /**
     * @var bool
     */
    protected $dispatched;

    /**
     * @var \Custom\Module\Model\Routing\Entity[]
     */
    protected $routingEntities;

    /**
     * @param ActionFactory $actionFactory
     * @param ManagerInterface $eventManager
     * @param UrlInterface $url
     * @param State $appState
     * @param StoreManagerInterface $storeManager
     * @param ResponseInterface $response
     * @param ScopeConfigInterface $scopeConfig
     * @param array $routingEntities
     */
    public function __construct(
    ActionFactory $actionFactory, ManagerInterface $eventManager, UrlInterface $url, State $appState, StoreManagerInterface $storeManager, ResponseInterface $response, ScopeConfigInterface $scopeConfig, ResultFactory $resultFactory, array $routingEntities
    ) {
        $this->actionFactory = $actionFactory;
        $this->eventManager = $eventManager;
        $this->url = $url;
        $this->appState = $appState;
        $this->storeManager = $storeManager;
        $this->response = $response;
        $this->scopeConfig = $scopeConfig;
        $this->routingEntities = $routingEntities;
        $this->resultFactory = $resultFactory;
    }

    /**
     * Validate and Match
     *
     * @param \Magento\Framework\App\RequestInterface $request
     * @return bool
     */
    public function match(\Magento\Framework\App\RequestInterface $request) {

        if (!$this->dispatched) {
            $urlKey = trim($request->getPathInfo(), '/');
            $origUrlKey = $urlKey;

            // START FOR POST MESSAGE FORM REDIRECT
            if (strpos($request->getServer('REQUEST_URI'), 'reply') !== false) {
                $request->setModuleName('Module')->setControllerName('posts')->setActionName('reply');

                return $this->actionFactory->create(
                                'Magento\Framework\App\Action\Forward', ['request' => $request]
                );
            }
            // END FOR POST MESSAGE FORM REDIRECT

            // START CHECK FOR URL KEY EXIST THEN ONLY PROCEED OTHERWIES NOT
            $postsURLPrefix = $this->scopeConfig->getValue('Module/posts/url_prefix', ScopeInterface::SCOPE_STORE);
            $postsURLSuffix = $this->scopeConfig->getValue('Module/posts/url_suffix', ScopeInterface::SCOPE_STORE);
            $parts = explode('/', $urlKey);

            if ($postsURLSuffix) {
                $suffix = substr($urlKey, -strlen($postsURLSuffix) - 1);
                if ($suffix != '.' . $postsURLSuffix) {
                    return false;
                }
                $urlKey = substr($urlKey, 0, -strlen($postsURLSuffix) - 1);
            }

            if (isset($parts[1])) {
                $postsIdentifier = str_replace($suffix, "", $parts[1]); // Posts URL Key
                // START CHECK FOR PREFIX & SUFFIX
                if ($parts[0] == $postsURLPrefix && $postsURLSuffix == $postsURLSuffix) {

                    // START CHECK FOR URL KEY EXIST THEN ONLY PROCEED OTHERWIES NOT
                    $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
                    $instance = $objectManager->get('Custom\Module\Model\ResourceModel\Posts');
                    $id = $instance->checkUrlKey($postsIdentifier, $this->storeManager->getStore()->getId());

                    if (!$id) {
                        return null;
                    }
                    // STOP CHECK FOR URL KEY EXIST THEN ONLY PROCEED OTHERWIES NOT

                    $condition = new DataObject(['url_key' => $origUrlKey, 'continue' => true]);
                    $this->eventManager->dispatch(
                            'Custom_Module_controller_router_match_before', ['router' => $this, 'condition' => $condition]
                    );

                    $origUrlKey = $condition->getUrlKey();

                    if ($condition->getRedirectUrl()) {

                        $this->response->setRedirect($condition->getRedirectUrl());
                        $request->setDispatched(true);
                        return $this->actionFactory->create(Redirect::class);
                    }

                    if (!$condition->getContinue()) {
                        return null;
                    }

                    foreach ($this->routingEntities as $entityKey => $entity) {
                        $match = $this->matchRoute($request, $entity, $origUrlKey, $origUrlKey);
                        if ($match === false) {
                            continue;
                        }
                        return $match;
                    }
                }
            }
            // END CHECK FOR PREFIX & SUFFIX
        }

        return null;
    }

    /**
     * @param RequestInterface|\Magento\Framework\HTTP\PhpEnvironment\Request $request
     * @param Entity $entity
     * @param $urlKey
     * @param $origUrlKey
     * @return bool|\Magento\Framework\App\ActionInterface|null
     */
    protected function matchRoute(RequestInterface $request, Entity $entity, $urlKey, $origUrlKey) {

        $prefix = $this->scopeConfig->getValue($entity->getPrefixConfigPath(), ScopeInterface::SCOPE_STORE);

        if ($prefix) {
            $parts = explode('/', $urlKey);
            if ($parts[0] != $prefix || count($parts) != 2) {
                return false;
            }
            $urlKey = $parts[1];
        }

        $configSuffix = $this->scopeConfig->getValue($entity->getSuffixConfigPath(), ScopeInterface::SCOPE_STORE);

        if ($configSuffix) {
            $suffix = substr($urlKey, -strlen($configSuffix) - 1);
            if ($suffix != '.' . $configSuffix) {
                return false;
            }
            $urlKey = substr($urlKey, 0, -strlen($configSuffix) - 1);
        }

        $instance = $entity->getFactory()->create();
        $id = $instance->checkUrlKey($urlKey, $this->storeManager->getStore()->getId());

        if (!$id) {
            return null;
        }

        $request->setModuleName('Module');
        $request->setControllerName($entity->getController());
        $request->setActionName($entity->getViewAction());
        $request->setParam($entity->getParam(), $id);
        $request->setAlias(Url::REWRITE_REQUEST_PATH_ALIAS, $origUrlKey);
        $request->setDispatched(true);
        $this->dispatched = true;

        return $this->actionFactory->create(Forward::class);
    }
}

app\code\Custom\Module\Controller\Posts\Reply.php

namespace Custom\Module\Controller\Posts;

use Magento\Framework\App\Request\DataPersistorInterface;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\App\Filesystem\DirectoryList;

class Reply  {

    /**
     * @var DataPersistorInterface
     */
    private $dataPersistor;

    /**
     * Post user post
     *
     * @return void
     * @throws \Exception
     */
    public function execute() {
        $post = $this->getRequest()->getPostValue();

        echo "in";
        exit;
 }
}

Give below error.

1 exception(s): Exception #0 (LogicException): Front controller reached 100 router match iterations

I'm already following

https://github.com/tzyganu/Magento2SampleModule

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

For other simple listing pages, it works fine only issue with Post Form.

Это было полезно?

Решение

Finally, I have SOLVED the issue.

No changes in di.xml.

Below are the changes I have made:

app\code\Custom\Module\Controller\Router.php removed check condition.

namespace Custom\Module\Controller;

use Magento\Framework\App\ActionFactory;
use Magento\Framework\App\Action\Forward;
use Magento\Framework\App\Action\Redirect;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\App\ResponseInterface;
use Magento\Framework\App\RouterInterface;
use Magento\Framework\App\State;
use Magento\Framework\DataObject;
use Magento\Framework\Event\ManagerInterface;
use Magento\Framework\Url;
use Magento\Framework\UrlInterface;
use Magento\Store\Model\ScopeInterface;
use Magento\Store\Model\StoreManagerInterface;
use Custom\Module\Model\Routing\Entity;
use Magento\Framework\Controller\ResultFactory;

class Router implements RouterInterface {

    /**
     * @var \Magento\Framework\App\ActionFactory
     */
    protected $actionFactory;

    /**
     * Event manager
     * @var \Magento\Framework\Event\ManagerInterface
     */
    protected $eventManager;

    /**
     * Store manager
     * @var \Magento\Store\Model\StoreManagerInterface
     */
    protected $storeManager;

    /**
     * Posts factory
     * @var \Custom\Module\Model\PostsFactory
     */
    protected $postsFactory;

    /**
     * Config primary
     * @var \Magento\Framework\App\State
     */
    protected $appState;

    /**
     * Url
     * @var \Magento\Framework\UrlInterface
     */
    protected $url;

    /**
     * Response
     * @var \Magento\Framework\App\ResponseInterface|\Magento\Framework\App\Response\Http
     */
    protected $response;

    /**
     * @var \Magento\Framework\App\Config\ScopeConfigInterface
     */
    protected $scopeConfig;

    /**
     * @var bool
     */
    protected $dispatched;

    /**
     * @var \Custom\Module\Model\Routing\Entity[]
     */
    protected $routingEntities;

    /**
     * @param ActionFactory $actionFactory
     * @param ManagerInterface $eventManager
     * @param UrlInterface $url
     * @param State $appState
     * @param StoreManagerInterface $storeManager
     * @param ResponseInterface $response
     * @param ScopeConfigInterface $scopeConfig
     * @param array $routingEntities
     */
    public function __construct(
    ActionFactory $actionFactory, ManagerInterface $eventManager, UrlInterface $url, State $appState, StoreManagerInterface $storeManager, ResponseInterface $response, ScopeConfigInterface $scopeConfig, ResultFactory $resultFactory, array $routingEntities
    ) {
        $this->actionFactory = $actionFactory;
        $this->eventManager = $eventManager;
        $this->url = $url;
        $this->appState = $appState;
        $this->storeManager = $storeManager;
        $this->response = $response;
        $this->scopeConfig = $scopeConfig;
        $this->routingEntities = $routingEntities;
        $this->resultFactory = $resultFactory;
    }

    /**
     * Validate and Match
     *
     * @param \Magento\Framework\App\RequestInterface $request
     * @return bool
     */
    public function match(\Magento\Framework\App\RequestInterface $request) {

        if (!$this->dispatched) {
            $urlKey = trim($request->getPathInfo(), '/');
            $origUrlKey = $urlKey;

            // START CHECK FOR URL KEY EXIST THEN ONLY PROCEED OTHERWIES NOT
            $postsURLPrefix = $this->scopeConfig->getValue('Module/posts/url_prefix', ScopeInterface::SCOPE_STORE);
            $postsURLSuffix = $this->scopeConfig->getValue('Module/posts/url_suffix', ScopeInterface::SCOPE_STORE);
            $parts = explode('/', $urlKey);

            if ($postsURLSuffix) {
                $suffix = substr($urlKey, -strlen($postsURLSuffix) - 1);
                if ($suffix != '.' . $postsURLSuffix) {
                    return false;
                }
                $urlKey = substr($urlKey, 0, -strlen($postsURLSuffix) - 1);
            }

            if (isset($parts[1])) {
                $postsIdentifier = str_replace($suffix, "", $parts[1]); // Posts URL Key
                // START CHECK FOR PREFIX & SUFFIX
                if ($parts[0] == $postsURLPrefix && $postsURLSuffix == $postsURLSuffix) {

                    // START CHECK FOR URL KEY EXIST THEN ONLY PROCEED OTHERWIES NOT
                    $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
                    $instance = $objectManager->get('Custom\Module\Model\ResourceModel\Posts');
                    $id = $instance->checkUrlKey($postsIdentifier, $this->storeManager->getStore()->getId());

                    if (!$id) {
                        return null;
                    }
                    // STOP CHECK FOR URL KEY EXIST THEN ONLY PROCEED OTHERWIES NOT

                    $condition = new DataObject(['url_key' => $origUrlKey, 'continue' => true]);
                    $this->eventManager->dispatch(
                            'Custom_Module_controller_router_match_before', ['router' => $this, 'condition' => $condition]
                    );

                    $origUrlKey = $condition->getUrlKey();

                    if ($condition->getRedirectUrl()) {

                        $this->response->setRedirect($condition->getRedirectUrl());
                        $request->setDispatched(true);
                        return $this->actionFactory->create(Redirect::class);
                    }

                    if (!$condition->getContinue()) {
                        return null;
                    }

                    foreach ($this->routingEntities as $entityKey => $entity) {
                        $match = $this->matchRoute($request, $entity, $origUrlKey, $origUrlKey);
                        if ($match === false) {
                            continue;
                        }
                        return $match;
                    }
                }
            }
            // END CHECK FOR PREFIX & SUFFIX
        }

        return null;
    }

    /**
     * @param RequestInterface|\Magento\Framework\HTTP\PhpEnvironment\Request $request
     * @param Entity $entity
     * @param $urlKey
     * @param $origUrlKey
     * @return bool|\Magento\Framework\App\ActionInterface|null
     */
    protected function matchRoute(RequestInterface $request, Entity $entity, $urlKey, $origUrlKey) {

        $prefix = $this->scopeConfig->getValue($entity->getPrefixConfigPath(), ScopeInterface::SCOPE_STORE);

        if ($prefix) {
            $parts = explode('/', $urlKey);
            if ($parts[0] != $prefix || count($parts) != 2) {
                return false;
            }
            $urlKey = $parts[1];
        }

        $configSuffix = $this->scopeConfig->getValue($entity->getSuffixConfigPath(), ScopeInterface::SCOPE_STORE);

        if ($configSuffix) {
            $suffix = substr($urlKey, -strlen($configSuffix) - 1);
            if ($suffix != '.' . $configSuffix) {
                return false;
            }
            $urlKey = substr($urlKey, 0, -strlen($configSuffix) - 1);
        }

        $instance = $entity->getFactory()->create();
        $id = $instance->checkUrlKey($urlKey, $this->storeManager->getStore()->getId());

        if (!$id) {
            return null;
        }

        $request->setModuleName('Module');
        $request->setControllerName($entity->getController());
        $request->setActionName($entity->getViewAction());
        $request->setParam($entity->getParam(), $id);
        $request->setAlias(Url::REWRITE_REQUEST_PATH_ALIAS, $origUrlKey);
        $request->setDispatched(true);
        $this->dispatched = true;

        return $this->actionFactory->create(Forward::class);
    }
}

app\code\Custom\Module\Controller\Reply\Index.php

namespace Custom\Module\Controller\Reply;

class Index extends \Magento\Framework\App\Action\Action {

    /** @var  \Magento\Framework\View\Result\Page */
    protected $resultPageFactory;

    /**     * @param \Magento\Framework\App\Action\Context $context      */
    public function __construct(\Magento\Framework\App\Action\Context $context, \Magento\Framework\View\Result\PageFactory $resultPageFactory) {
        $this->resultPageFactory = $resultPageFactory;
        parent::__construct($context);
    }

    /**
     * Blog Index, shows a list of recent blog posts.
     *
     * @return \Magento\Framework\View\Result\PageFactory
     */
    public function execute() {
        $resultPage = $this->resultPageFactory->create();

        $post = $this->getRequest()->getPostValue();

        echo "<pre>";
        print_r($post);
        exit;

        return $resultPage;
    }
}

Другие советы

I also faced the same error. I debugged it and found the working solution for the same. Adding the code here. Module name - Inchoo_CustomRouter

Registration.php :: app/code/Inchoo/CustomRouter/registration.php

<?php

\Magento\Framework\Component\ComponentRegistrar::register(
        \Magento\Framework\Component\ComponentRegistrar::MODULE, 'Inchoo_CustomRouter', __DIR__
);

Module.xml :: app/code/Inchoo/CustomRouter/etc/module.xml

<?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/Module/etc/module.xsd">
    <module name="Inchoo_CustomRouter" setup_version="2.0.0"></module>
</config>

di.xml :: app/code/Inchoo/CustomRouter/etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">

</config>

routes.xml :: app/code/Inchoo/CustomRouter/etc/frontend/routes.xml

<?xml version="1.0"?>
<!--
/**
 * Copyright © 2016 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="standard">
        <route id="inchootest" frontName="inchootest">
            <module name="Inchoo_CustomRouter" />
        </route>
    </router>
</config>

di.xml :: app/code/Inchoo/CustomRouter/etc/frontend/di.xml Here we are passing the router file path and the sort order for the router

<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
 * Copyright © 2016 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn: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">61</item>
                </item>
            </argument>
        </arguments>
    </type>
</config>

Routes.php :: app/code/Inchoo/CustomRouter/Controller/Router.php

<?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) {
        /*
         * You can use any name in URL and add condition for that name here to redirect it. Here we are accessing customrouting 
         * and if the we get the same, the we will redirect the request to controller action.
         * 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
         */
       // $a = explode('/', $_SERVER['REQUEST_URI']);
        // $postId = end($a);  [if you want to pass parameter also.]
        //exit;
        $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', 4); // specify the page id
        } else if (strpos($identifier, 'customrouting') !== false) {
            /*
             * We must set module, controller path and action name for our controller class(Controller/Test/Test.php)
             */
            $request->setModuleName('CustomRouter')->setControllerName('test')->setActionName('test');

            // $request->setParam('id', $postId); [if passing params]
        } 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]
        );
    }

}


/* you will face iteration error if the controller you are trying to access is not available*/

Test.php :: app/code/Inchoo/CustomRouter/Controller/Test/Test.php

<?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()");
    }

}

I have added small working example, it may helps to you.

app\code\Vendor\Module\registration.php

<?php
/**
 * Copyright © 2015 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Vendor_Module',
    __DIR__
);

\app\code\Vendor\Module\etc\module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
    <module name="Vendor_Module" setup_version="2.0.0"></module>
</config>

\app\code\Vendor\Module\etc\frontend\routes.xml

<?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="sometest" frontName="sometest">
            <module name="Vendor_Module" />
        </route>
    </router>
</config>

\app\code\Vendor\Module\etc\frontend\di.xml

<?xml version="1.0"?>
<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="sometest" xsi:type="array">
                    <item name="class" xsi:type="string">Vendor\Module\Controller\Router</item>
                    <item name="disable" xsi:type="boolean">false</item>
                    <item name="sortOrder" xsi:type="string">1</item>
                </item>
            </argument>
        </arguments>
    </type>
</config>

\app\code\Vendor\Module\Controller\Router.php

 <?php
    namespace Vendor\Module\Controller;


    class Router implements \Magento\Framework\App\RouterInterface
    {
        protected $actionFactory;
        protected $_response;
        public function __construct(
            \Magento\Framework\App\ActionFactory $actionFactory,
            \Magento\Framework\App\ResponseInterface $response
        ) {
            $this->actionFactory = $actionFactory;
            $this->_response = $response;
        }

        public function match(\Magento\Framework\App\RequestInterface $request)
        {

            //$request->setModuleName('module')->setControllerName('test')->setActionName('test');
$request->setModuleName('cms')->setControllerName('page')->setActionName('view')->setParam('page_id', 4);
            return $this->actionFactory->create(
                'Magento\Framework\App\Action\Forward',
                ['request' => $request]
            );
        }
    }

For testing i have forwarded to a CMS page even i tested with my custom controller.

$request->setModuleName('cms')->setControllerName('page')->setActionName('view')->setParam('page_id', 4);

I just came across a similar problem.

The problem here is that the sortOrder in the di.xml is set to 22 which is higher in priority than the sortOrder of 30 for the standard router, see https://devdocs.magento.com/guides/v2.3/extension-dev-guide/routing.html for reference

With the way a usual CustomRouter in web tutorials looks like, and maybe even more important: the Magento Dev Doc example looks like,

public function match(RequestInterface $request): ?ActionInterface
{
    $identifier = trim($request->getPathInfo(), '/');

    if (strpos($identifier, 'learning') !== false) {
        $request->setModuleName('routing');
        $request->setControllerName('index');
        $request->setActionName('index');
        $request->setParams([
            'first_param' => 'first_value',
            'second_param' => 'second_value'
        ]);

        return $this->actionFactory->create(Forward::class, ['request' => $request]);
    }

    return null;
}

now this is what happens:

  1. Call of some URL (http://storeurl/learning)
  2. Custom Router fires
  3. URL matches if condition
  4. Router sets request parameters
  5. Router forwards the request
  6. Since requestPath doesn't change and Custom Router fires before standard router: Start over with 2
  7. Infinite Loop

You can fix this by changing sortOrder from 22 to 40 (or something else above 30, see link above for reference of priorities)

Now it looks like this:

  1. Call of some URL (http://storeurl/learning)
  2. standard router doesn't find a match
  3. Custom Router fires
  4. URL matches if condition
  5. Router sets request parameters
  6. Router forwards the request
  7. Now the standard router matches the request to the correct Controller based on the changed request parameters

This might not be the solution in all use cases, sometimes you might want to have priority over the standard router. But I think in the default case this might be a better solution than changing the matching logic.

I am also facing an issue with my custom router.

The url i want to implement is something like this

/brand-products/:brandName

I've already set the router like this

   public function match(\Magento\Framework\App\RequestInterface $request) {
    $identifier = trim($request->getPathInfo(), '/');

    if (strpos($identifier, 'brand-products') !== false) {
        //$request->setModuleName('cms')->setControllerName('page')->setActionName('view')->setParam('page_id', 4); // specify the page id
        $request->setModuleName('MyModule')->setControllerName('brands')->setActionName('index');
    } 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]
    );
}

Problem is that i am getting

Exception #0 (LogicException): Front controller reached 100 router match iterations

When commenting out this line and enabling the "cms" test line everthing works as expected.

My module name is Vendor_ModuleName

and the route ( the real one ) is set like

    <router id="standard">
    <route frontName="brand-products" id="brandproducts">
        <module name="Vendor_ModuleName"/>
    </route>
</router>

SOLUTION

We have to put the route front name in setModuleName and NOT the module name itself.

You can get the front name of the router in ther routes.xml, mine is brand-products

<route frontName="brand-products" id="brandproducts">
    <module name="Vendor_ModuleName"/>
</route>
Лицензировано под: CC-BY-SA с атрибуция
Не связан с magento.stackexchange
scroll top