Skip to content

Serialization of 'Closure' is not allowed on Route group and resources #17149

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
webmake opened this issue Jan 4, 2017 · 9 comments
Closed

Comments

@webmake
Copy link
Contributor

webmake commented Jan 4, 2017

  • Laravel Version: 5.2.45
  • PHP Version: 5.6.27

Description:

I got very strange case (THIS IS NOT related with #7319), I don't use closures, but still got error:
develop.ERROR: exception 'Exception' with message 'Serialization of 'Closure' is not allowed' in /vagrant/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Console/RouteCacheCommand.php:95

After some hours of debugging I noticed, seems $route->prepareForSerialization(); somehow failing, that cannot unset $this->router, $this->container parameters within route object.
More strange, that code below works perfectly: routes.php:

Route::group(['prefix' => 'api'], function () {
    Route::group(['middleware' => ['role:api']], function () {
        Route::get('/users', 'ApiUsersController@index');
    });
});

$routes = app('router')->getRoutes();
foreach ($routes as $route) {
    $route->prepareForSerialization(); // magical line
}
serialize($routes); // no error

But if I runphp artisan route:cache
and comment magical line - doesn't work and gives error.

One more detail that I noticed:
serialize($routes->getByAction('App\Http\Controllers\ApiUsersController@index'));
this fails, don't neccesary to serialize whole object (serialize($routes) ). I guess pointer to router object somewhere got lost, because actionList is not unset from router and container parameters.

Currently I cannot give more details, but if anyone is familiar how routing cache works, please guide me.
Thanks

@webmake
Copy link
Contributor Author

webmake commented Jan 5, 2017

Finally found peace of code, which causes such error (I guess when url and method is the same):

Route::group(['prefix' => 'api'], function () {
    Route::get('/users', 'ApiUsersController@index');
});

Route::group(['prefix' => 'api'], function () {
    Route::get('/users', 'Modules\ApiUsersController@index');
});

Please qualify, is it bug of library that gives not proper message, or bug, that cannot handle such case, because having multiple modules, when error occurs can't even determine error place.

@sisve
Copy link
Contributor

sisve commented Jan 5, 2017

The error message could perhaps be improved, but isn't the issue that you have duplicate routes? How is that expected to work?

I can reproduce this in 5.1.45, it is not limited to unsupported 5.2

[error] Exception: Serialization of 'Closure' is not allowed in ~/vendor/laravel/framework/src/Illuminate/Foundation/Console/RouteCacheCommand.php:95
Stack trace:
#0 ~/vendor/laravel/framework/src/Illuminate/Foundation/Console/RouteCacheCommand.php(95): serialize(Object(Illuminate\Routing\RouteCollection))
#1 ~/vendor/laravel/framework/src/Illuminate/Foundation/Console/RouteCacheCommand.php(65): Illuminate\Foundation\Console\RouteCacheCommand->buildRouteCacheFile(Object(Illuminate\Routing\RouteCollection))
#2 [internal function]: Illuminate\Foundation\Console\RouteCacheCommand->fire()

@sisve
Copy link
Contributor

sisve commented Jan 5, 2017

I've reduced the reproduction further. This happens if you have 1) two routes for same method+url, and 2) at least one of the controllers is in a namespace, and 2) they are not in the same namespace.

Route::get('/', 'Alfa\\NonExisting@index');
Route::get('/', 'Beta\\NonExisting@index');

This is reproducible in Laravel 5.1.45.

@webmake
Copy link
Contributor Author

webmake commented Jan 5, 2017

Well, I think validation before generating urls should prevent from such errors, because having huge application hard to track if url is in use, so it might redeclare controller for the same route even without deeper knowledge. I admit that was my mistake to declare twice, but message is really unhelpful to track where it fails for real

@webmake
Copy link
Contributor Author

webmake commented Jan 7, 2017

My proposal would be:
--- src/Illuminate/Routing/RouteCollection.php
+++ src/Illuminate/Routing/RouteCollection.php

    protected function addToCollections($route)
    {
        $domainAndUri = $route->domain().$route->getUri();

        foreach ($route->methods() as $method) {
+            if (isset($this->routes[$method][$domainAndUri])) {
+                throw new DuplicateKeyException('Method: ' . $method . ' route: ' . $domainAndUri);
+            }
            $this->routes[$method][$domainAndUri] = $route;
        }

        $this->allRoutes[$method.$domainAndUri] = $route;
    }

Does anyone agree with me? :)

@marky291
Copy link

I don't see a reason to bloat code and having this run every time you call routes.php.

It isn't that hard to see duplicate urls to be honest.

@webmake
Copy link
Contributor Author

webmake commented Jan 22, 2017

Well, reason is that exception doesn't refer to the real problem. Even more I didn't find any info in laravel docs, that duplicated url might cause not generated cache at all due this error. It cost a lot time to detect real place that causes such exception, having prefixed urls in different modules, etc. so I think additional one line checking isn't so much cost to prevent from future problems. It should inform at very begining of developing that something wrong, not at that time when trying to enable cache.

@marky291
Copy link

Maybe a check to see if application is running artisan route cache.

You should create a pull request and it will be either accepted or denied, more progressive.

@webmake
Copy link
Contributor Author

webmake commented Apr 3, 2017

Seems solved with #18475 with route overload, not with suggested exception, but well done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants