Search code examples
phpsymfonysymfony5symfony-routing

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


I'm having a hard time trying to configure my routes using a config/routes.php file in Symfony 5.1.

As per the Symfony routing documentation, I should be able to configure my routes in a PHP file:

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.

But in practice, Symfony only recognizes the routes if I put my routes in a file routes.yaml.

Routes configured inside a file routes.php result in the error "No route found for "GET /something" (404 Not Found)". When running debug:router, these routes are not listed.

The same route works great when configured in routes.yaml.

In a different project using Symfony 5.0.8, route configuration via routes.php is working like a charm.

This is how I tested it:

  1. Created a controller (omitted, since it's no relevant, any controller would do)

  2. Created a routes.php file:

//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. Running debug:router will result in:
 ---------------- -------- -------- ------ -------------------------- 
  Name             Method   Scheme   Host   Path                      
 ---------------- -------- -------- ------ -------------------------- 
  _preview_error   ANY      ANY      ANY    /_error/{code}.{_format}  
 ---------------- -------- -------- ------ -------------------------- 
  1. Configured the same route inside routes.yaml:
#config/routes.yaml
schools_list:
    path: /schools
    controller: App\Controller\SchoolController::list
    methods: GET
  1. Running debug:router will result in:
 ---------------- -------- -------- ------ -------------------------- 
  Name             Method   Scheme   Host   Path                      
 ---------------- -------- -------- ------ -------------------------- 
  _preview_error   ANY      ANY      ANY    /_error/{code}.{_format}  
  schools_list     GET      ANY      ANY    /schools                  
 ---------------- -------- -------- ------ -------------------------- 

Solution

  • On Symfony < 5.1, the default Kernel::configureRoutes() looked like 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');
    }
    

    Notice specifically Kernel::CONFIG_EXTS, which is set to:

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

    So it will try loading routes from PHP, XML OR YAML files (it will even attempt to load YAML from files with the .yml extension).

    But on Symfony 5.1+, this method 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');
    }
    

    Now it only attempts to load YAML files by default. Yup, sad. But it has a very easy fix.

    (Notice also that RouteCollectionBuilder has been replaced with RoutingConfigurator, since type-hinting the former has been deprecated on 5.1).

    Just change your Kernel::configureRoutes() to account for your PHP files:

    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");
    }
    

    And you will be ready to go.