Контроллер определяется RequestListener
, а именно маршрутизатором RouterListener
. Это, в свою очередь, использует UrlMatcher
для проверки URI против RouteCollection
. Вы могли бы реализовать Matcher
, который разрешает контроллер на основе маршрута. Все, что вам нужно сделать, это вернуть массив с ключом _controller
.
Обратите внимание, что это решение не позволит вам генерировать URL-адрес из имени маршрута, поскольку это отличается Interface
, но вы можете соединить его вместе.
// src/Routing/NaiveRequestMatcher
namespace App\Routing;
use App\Controller\RestController;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
use Symfony\Component\Routing\RequestContext;
class NaiveRequestMatcher implements UrlMatcherInterface
{
private $matcher;
/**
* @param $matcher The original 'router' service (implements UrlMatcher)
*/
public function __construct($matcher)
{
$this->matcher = $matcher;
}
public function setContext(RequestContext $context)
{
return $this->matcher->setContext($context);
}
public function getContext()
{
return $this->matcher->getContext();
}
public function match(string $pathinfo)
{
try {
// Check if the route is already defined
return $this->matcher->match($pathinfo);
} catch (ResourceNotFoundException $resourceNotFoundException) {
// Allow only GET requests
if ('GET' != $this->getContext()->getMethod()) {
throw $resourceNotFoundException;
}
// Get the first component of the uri
$routeName = current(explode('/', ltrim($pathinfo, '/')));
// Check that the method is available...
$baseControllerClass = RestController::class;
$controller = $baseControllerClass.'::action'.ucfirst($routeName);
if (is_callable($controller)) {
return [
'_controller' => $controller,
];
}
// Or bail
throw $resourceNotFoundException;
}
}
}
Теперь вам нужно переопределить конфигурацию Listener
:
// config/services.yaml
Symfony\Component\HttpKernel\EventListener\RouterListener:
arguments:
- '@App\Routing\NaiveRequestMatcher'
App\Routing\NaiveRequestMatcher:
arguments:
- '@router.default'
Не уверен, что это лучший подход, но кажется более простым. Другой вариант, который приходит на ум, - это подключиться к самому RouteCompiler
.