You can do this by creating a module as follows.
Create a new module and add these files:
1) Your\Module\Controller\NoRouteHandler.php
<?php
namespace Your\Module\Controller;
use Magento\Framework\App\Router\NoRouteHandlerInterface;
class NoRouteHandler implements NoRouteHandlerInterface
{
public function process(\Magento\Framework\App\RequestInterface $request)
{
$request->setModuleName('404')->setControllerName('redirect')->setActionName('index');
}
}
Here we are creating a new NoRouteHandler
that will be used instead of the default Magento one that uses the cms/noroute/index
controller. We want to use a custom controller instead, in this case, 404/redirect/index
.
2) Your/Module/etc/frontend/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">
<type name="Magento\Framework\App\Router\NoRouteHandlerList">
<arguments>
<argument name="handlerClassesList" xsi:type="array">
<item name="redirect404" xsi:type="array">
<item name="class" xsi:type="string">Your\Module\Controller\NoRouteHandler</item>
<item name="sortOrder" xsi:type="string">20</item>
</item>
</argument>
</arguments>
</type>
</config>
This adds our handler to the NoRouteHandlerList
collection, placing it before the default Magento one by using a sort order of 20.
Now we need to declare a new route:
3) Your\Module\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 id="404" frontName="404">
<module name="Your_Module"/>
</route>
</router>
</config>
We need two controllers, the first controller is
4) Your\Module\Controller\Redirect\Index.php
<?php
namespace Your\Module\Controller\Redirect;
use Magento\Framework\App\Action\Action;
class Index extends Action
{
public function execute()
{
$this->_redirect('404');
}
}
This controller redirects to the "/404" url which corresponds to our other controller shown below which simply forwards to the cms\noroute\index
controller.
5) Your\Module\Controller\Index\Index.php
namespace AAllen\Test\Controller\Index;
use Magento\Framework\App\Action\Action;
class Index extends Action
{
public function execute()
{
$this->_forward('index', 'noroute', 'cms');
}
}
With this module in place, 404 pages will have the "/404" URL instead of whatever the user entered.