When caching routes they become unusable. I've tried tracking down the issue but cannot find the culprit.
I've debugged down the rabbit hole, but can't figure out why the RouteCollection isn't populated whilst being loaded from cache.
Route is listed fine in artisan route:list
a route:list | grep reports/source
| | GET|HEAD | reports/source | reports.generated::h6iLoxUpb7OSO9T1 | App\Http\Controllers\ReportController@loadSource | web,auth,App\Http\Middleware\TransformCommaStringToArray
But once it tries to load the route by name it fails as $this->routes nameList is empty. But getRoutes() can see them fine.

The error is also misleading, telling me that POST and DELETE are valid though they aren't?
MethodNotAllowedHttpException
HTTP 405 Method Not Allowed
The GET method is not supported for this route. Supported methods: HEAD, POST, DELETE.
Without cache the match method finds the route instantly

Facing same issue
Could you post the code that define the route (the /routes/web.php file) and the cached file /bootstrap/cache/routes-v7.php, please. Want to try to replicate the bug.
Is there still the old cache file?
It has been two days since release and i have not seen any comments from Laravel team.
I am happy to provide a sample laravel repo to debug.
Here is the RouteServiceProvider code
Route::middleware(['web'])
->as('admin.')
->domain(config('domains.admin.domain'))
->namespace($this->namespace.'\Admin')
->group(base_path('routes/web.php'));
Routes in web.php
Route::redirect('/', 'login', 302);
Route::get('login', 'Auth\LoginController@showLoginForm')->name('login');
// Notice that this route does not have a name
Route::post('login', 'Auth\LoginController@login');
Route::post('logout', 'Auth\LoginController@logout')->name('logout');
routes-v7.php content
<?php
/*
|--------------------------------------------------------------------------
| Load The Cached Routes
|--------------------------------------------------------------------------
|
| Here we will decode and unserialize the RouteCollection instance that
| holds all of the route information for an application. This allows
| us to instantaneously load the entire route map into the router.
|
*/
app('router')->setCompiledRoutes(
array (
'compiled' =>
array (
0 => true,
1 =>
array (
'/' =>
array (
0 =>
array (
0 =>
array (
'_route' => 'admin.',
),
1 => 'admin.example.test',
2 =>
array (
'GET' => 0,
'HEAD' => 1,
'POST' => 2,
'PUT' => 3,
'PATCH' => 4,
'DELETE' => 5,
'OPTIONS' => 6,
),
3 => NULL,
4 => false,
5 => false,
6 => NULL,
),
),
'/login' =>
array (
0 =>
array (
0 =>
array (
'_route' => 'admin.login',
),
1 => 'admin.example.test',
2 =>
array (
'GET' => 0,
'HEAD' => 1,
),
3 => NULL,
4 => false,
5 => false,
6 => NULL,
),
1 =>
array (
0 =>
array (
'_route' => 'generated::7Z6OFHMNFX8pu9Wc',
),
1 => 'admin.example.test',
2 =>
array (
'POST' => 0,
),
3 => NULL,
4 => false,
5 => false,
6 => NULL,
),
),
'/logout' =>
array (
0 =>
array (
0 =>
array (
'_route' => 'admin.logout',
),
1 => 'admin.example.test',
2 =>
array (
'POST' => 0,
),
3 => NULL,
4 => false,
5 => false,
6 => NULL,
),
),
),
2 =>
array (
),
3 =>
array (
),
4 => NULL,
),
'attributes' =>
array (
'admin.' =>
array (
'methods' =>
array (
0 => 'GET',
1 => 'HEAD',
2 => 'POST',
3 => 'PUT',
4 => 'PATCH',
5 => 'DELETE',
6 => 'OPTIONS',
),
'uri' => '/',
'action' =>
array (
'middleware' =>
array (
0 => 'web',
),
'domain' => 'admin.example.test',
'uses' => '\\Illuminate\\Routing\\RedirectController@__invoke',
'controller' => '\\Illuminate\\Routing\\RedirectController',
'as' => 'admin.',
'namespace' => 'App\\Http\\Controllers\\Admin',
'prefix' => NULL,
'where' =>
array (
),
),
'fallback' => false,
'defaults' =>
array (
'destination' => 'login',
'status' => 302,
),
'wheres' =>
array (
),
'bindingFields' =>
array (
),
),
'admin.login' =>
array (
'methods' =>
array (
0 => 'GET',
1 => 'HEAD',
),
'uri' => 'login',
'action' =>
array (
'middleware' =>
array (
0 => 'web',
),
'domain' => 'admin.example.test',
'uses' => 'App\\Http\\Controllers\\Admin\\Auth\\LoginController@showLoginForm',
'controller' => 'App\\Http\\Controllers\\Admin\\Auth\\LoginController@showLoginForm',
'as' => 'admin.login',
'namespace' => 'App\\Http\\Controllers\\Admin',
'prefix' => NULL,
'where' =>
array (
),
),
'fallback' => false,
'defaults' =>
array (
),
'wheres' =>
array (
),
'bindingFields' =>
array (
),
),
'admin.generated::7Z6OFHMNFX8pu9Wc' =>
array (
'methods' =>
array (
0 => 'POST',
),
'uri' => 'login',
'action' =>
array (
'middleware' =>
array (
0 => 'web',
),
'domain' => 'admin.example.test',
'uses' => 'App\\Http\\Controllers\\Admin\\Auth\\LoginController@login',
'controller' => 'App\\Http\\Controllers\\Admin\\Auth\\LoginController@login',
'as' => 'admin.generated::7Z6OFHMNFX8pu9Wc',
'namespace' => 'App\\Http\\Controllers\\Admin',
'prefix' => NULL,
'where' =>
array (
),
),
'fallback' => false,
'defaults' =>
array (
),
'wheres' =>
array (
),
'bindingFields' =>
array (
),
),
'admin.logout' =>
array (
'methods' =>
array (
0 => 'POST',
),
'uri' => 'logout',
'action' =>
array (
'middleware' =>
array (
0 => 'web',
),
'domain' => 'admin.example.test',
'uses' => 'App\\Http\\Controllers\\Admin\\Auth\\LoginController@logout',
'controller' => 'App\\Http\\Controllers\\Admin\\Auth\\LoginController@logout',
'as' => 'admin.logout',
'namespace' => 'App\\Http\\Controllers\\Admin',
'prefix' => NULL,
'where' =>
array (
),
),
'fallback' => false,
'defaults' =>
array (
),
'wheres' =>
array (
),
'bindingFields' =>
array (
),
),
),
)
);
Found out every route must have a name to make cache work. Not 100% sure.
Otherwise i am getting this error on login action
The POST method is not supported for this route. Supported methods: GET, HEAD.
Found the issue, will explain it and maybe @driesvints can fix the black magic behind it.
It comes down to us setting a name on the group
Route::name('lookup.')->prefix('lookup')->group(base_path('routes/web/lookup.php'));
In the group I have 2 urls now.
Route::get('/fake-news', [LookupController::class, 'source']);
Route::get('/source/{type}', [LookupController::class, 'source']);
a route:list +--------+----------+----------------------+---------+--------------------------------------------------+------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+----------+----------------------+---------+--------------------------------------------------+------------+
| | GET|HEAD | lookup/fake-news | lookup. | App\Http\Controllers\Api\LookupController@source | web |
| | GET|HEAD | lookup/source/{type} | lookup. | App\Http\Controllers\Api\LookupController@source | web |
+--------+----------+----------------------+---------+--------------------------------------------------+------------+
cached
a route:list
+--------+----------+----------------------+------------------------------------+--------------------------------------------------+------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+----------+----------------------+------------------------------------+--------------------------------------------------+------------+
| | GET|HEAD | lookup/fake-news | lookup. | App\Http\Controllers\Api\LookupController@source | web |
| | GET|HEAD | lookup/source/{type} | lookup.generated::rsfnRZ32JW2CM4gj | App\Http\Controllers\Api\LookupController@source | web |
+--------+----------+----------------------+------------------------------------+--------------------------------------------------+------------+
This then gives the 405 error. But if I switch the position of the routes, it gives a 200...
Route::get('/source/{type}', [LookupController::class, 'source']);
Route::get('/fake-news', [LookupController::class, 'source']);
cached
a route:list
+--------+----------+----------------------+------------------------------------+--------------------------------------------------+------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+----------+----------------------+------------------------------------+--------------------------------------------------+------------+
| | GET|HEAD | lookup/fake-news | lookup.generated::KIbM69Jcmm1a7iAa | App\Http\Controllers\Api\LookupController@source | web |
| | GET|HEAD | lookup/source/{type} | lookup. | App\Http\Controllers\Api\LookupController@source | web |
+--------+----------+----------------------+------------------------------------+--------------------------------------------------+------------+
Final solution is also to remove the name from group then everything works. But I still see it as a bug as it all works pre-cache.
Actually removing name from resource group isn't the way to go as we have same names in different namespaces, and since resources add a name automatically this will collide, so there needs to be a proper fix for this.
Route names need to be unique from now on. Please see https://laravel.com/docs/7.x/upgrade#unique-route-names
@danijelk The error seems to be related to a change we made for route group naming. We'll check in on this.
This then gives the 405 error. But if I switch the position of the routes, it gives a 200...
WHAT gives a 405 error?
This then gives the 405 error. But if I switch the position of the routes, it gives a 200...
WHAT gives a 405 error?
Sending a GET request for route 'reports/source'.
But I made a clearer case https://github.com/laravel/framework/issues/32015#issuecomment-601147924 with just 2 routes in one group, easier to understand and replicate.
We've released a fix for this. Thanks for reporting all.