You need to create custom router (matcher) for route to your action controller
1. Define your custom router
app/code/Acme/StackExchange/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\RouterList"> <arguments> <argument name="routerList" xsi:type="array"> <item name="acme_stackexchange" xsi:type="array"> <item name="class" xsi:type="string">Acme\StackExchange\Controller\Router</item> <item name="disable" xsi:type="boolean">false</item> <item name="sortOrder" xsi:type="string">50</item> </item> </argument> </arguments> </type> </config>
2. Create Routed and implement your match logic
app/code/Acme/StackExchange/Controller/Router.php
<?php declare(strict_types=1); namespace Acme\StackExchange\Controller; use Magento\Framework\App\Action\Forward as ActionForward; use Magento\Framework\App\ActionFactory; use Magento\Framework\App\RequestInterface; use Magento\Framework\App\ResponseInterface; use Magento\Framework\DataObject; use Magento\Framework\Event\ManagerInterface as EventManagerInterface; use Magento\Store\Model\StoreManagerInterface; class Router implements \Magento\Framework\App\RouterInterface { protected ActionFactory $actionFactory; protected EventManagerInterface $eventManager; protected StoreManagerInterface $storeManager; protected ResponseInterface $response; public function __construct( ActionFactory $actionFactory, EventManagerInterface $eventManager, StoreManagerInterface $storeManager, ResponseInterface $response ) { $this->actionFactory = $actionFactory; $this->eventManager = $eventManager; $this->storeManager = $storeManager; $this->response = $response; } /** * @inheritDoc */ public function match(RequestInterface $request) { $requestPath = $request->getPathInfo(); if (!str_contains($requestPath, '/some-review/')) { return null; } // optional create event $condition = new DataObject(['request' => $request, 'custom' => 'custom_value']); $this->eventManager->dispatch( 'acme_controller_router_match_before', ['router' => $this, 'condition' => $condition] ); // example to verify in store if needed $store = $this->storeManager->getStore(); // parse request and set your action if applicable $request->setModuleName('acme') ->setControllerName('result') ->setActionName('review'); // you can set dynamic variables to request like $request->setParam('param_name', 'param_value'); return $this->actionFactory->create(ActionForward::class); } }