为什么 Symfony 5.1 无法识别 "routes.php" 文件中配置的路由?

Why doesn't Symfony 5.1 recognize routes configured on a "routes.php" file?

我很难尝试使用 Symfony 5.1 中的 config/routes.php 文件配置我的路由。

根据 Symfony routing documentation,我应该能够在 PHP 文件中配置我的路由:

Instead of defining routes in the controller classes, you can define them in a separate YAML, XML or PHP file. The main advantage is that they don't require any extra dependency.

但实际上,Symfony 仅在我将路由放入文件中时才识别路由 routes.yaml

在文件 routes.php 中配置的路由导致错误 "No route found for "GET /something" (404 Not Found)"。当运行 debug:router时,这些路由没有列出。

routes.yaml 中配置相同的路由时效果很好。

在另一个使用 Symfony 5.0.8 的项目中,通过 routes.php 进行路由配置非常有效。

我是这样测试的:

  1. 创建了控制器(省略,因为不相关,任何控制器都可以)

  2. 创建了一个 routes.php 文件:

//config/routes.php example

use App\Controller;
use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;

return function(RoutingConfigurator $routes)
{
    $routes->add('schools_list', '/schools')
        ->controller([Controller\SchoolController::class, 'list'])
        ->methods(['GET']);
};
  1. 运行 debug:router 将导致:
 ---------------- -------- -------- ------ -------------------------- 
  Name             Method   Scheme   Host   Path                      
 ---------------- -------- -------- ------ -------------------------- 
  _preview_error   ANY      ANY      ANY    /_error/{code}.{_format}  
 ---------------- -------- -------- ------ -------------------------- 
  1. routes.yaml里面配置了相同的路由:
#config/routes.yaml
schools_list:
    path: /schools
    controller: App\Controller\SchoolController::list
    methods: GET
  1. 运行 debug:router 将导致:
 ---------------- -------- -------- ------ -------------------------- 
  Name             Method   Scheme   Host   Path                      
 ---------------- -------- -------- ------ -------------------------- 
  _preview_error   ANY      ANY      ANY    /_error/{code}.{_format}  
  schools_list     GET      ANY      ANY    /schools                  
 ---------------- -------- -------- ------ -------------------------- 

在 Symfony < 5.1 上,默认 Kernel::configureRoutes() 看起来像 this:

protected function configureRoutes(RouteCollectionBuilder $routes): void
{
    $confDir = $this->getProjectDir().'/config';

    $routes->import($confDir.'/{routes}/'.$this->environment.'/*'.self::CONFIG_EXTS, '/', 'glob');
    $routes->import($confDir.'/{routes}/*'.self::CONFIG_EXTS, '/', 'glob');
    $routes->import($confDir.'/{routes}'.self::CONFIG_EXTS, '/', 'glob');
}

具体注意Kernel::CONFIG_EXTS,其中is set to

private const CONFIG_EXTS = '.{php,xml,yaml,yml}';

因此它将尝试从 PHP、XML 或 YAML 文件加载路由(它甚至会尝试从具有 .yml 扩展名的文件加载 YAML)。

但是在 Symfony 5.1+ 上,这个方法 has been changed to:

protected function configureRoutes(RoutingConfigurator $routes): void
{
    $routes->import('../config/{routes}/'.$this->environment.'/*.yaml');
    $routes->import('../config/{routes}/*.yaml');
    $routes->import('../config/{routes}.yaml');
}

现在它默认只尝试加载 YAML 文件。是的,悲伤。但它有一个非常简单的修复方法。

(另请注意,RouteCollectionBuilder 已替换为 RoutingConfigurator,因为前者的类型提示已在 5.1 上被 弃用 )。

只需更改您的 Kernel::configureRoutes() 以说明您的 PHP 个文件:

protected function configureRoutes(RoutingConfigurator $routes): void
{
    $extensions = '{php,yaml}';

    $routes->import('../config/{routes}/' . $this->environment . "/*.$extensions");
    $routes->import("../config/{routes}/*.$extensions");
    $routes->import("../config/{routes}.$extensions");
}

你就可以开始了。