Symfony 5动态路由解析

问题描述 投票:0回答:1

我正在将旧项目路由(Yii1)迁移到Symfony 5

现在我的config/routing.yaml看起来像这样:

- {path: '/login', methods: ['GET'], controller: 'App\Controller\RestController::actionLogin'}
- {path: '/logout', methods: ['GET'], controller: 'App\Controller\RestController::actionLogout'}
# [...]
- {path: '/readme', methods: ['GET'], controller: 'App\Controller\RestController::actionReadme'}

您可以看到,有很多重复的urlaction转换。

是否有可能根据某些参数动态解析控制器方法。例如:

- {path: '/{action<login|logout|...|readme>}', methods: ['GET'], controller: 'App\Controller\RestController::action<action>'}

一种选择是编写批注,但这对我不起作用并抛出Route.php not found

symfony url-routing fosrestbundle symfony5
1个回答
0
投票

[控制器由RequestListener,特别是路由器RouterListener确定。依次使用RouterListener来对照UrlMatcher检查uri。您可以实现一个RouteCollection来根据路由解析控制器。您要做的就是用Matcher键返回一个数组。

请注意,此解决方案不允许您从路由名称生成网址,因为它是_controller,但您可以将其连接在一起。

different Interface

现在您需要覆盖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 $resourceNotFoundHttpException) {
            // Allow only GET requests
            if ('GET' != $this->getContext()->getMethod()) {
                throw $resourceNotFoundHttpException;
            }

            // 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 $resourceNotFoundHttpException;
        }
    }
}

不确定这是否是最好的方法,但似乎更简单。我想到的另一个选择是插入Listener本身。

© www.soinside.com 2019 - 2024. All rights reserved.