Skip to content

[7.x] Fix null value injected from container in routes#31867

Merged
taylorotwell merged 2 commits intolaravel:7.xfrom
mathieutu:fixes/container-routes
Mar 12, 2020
Merged

[7.x] Fix null value injected from container in routes#31867
taylorotwell merged 2 commits intolaravel:7.xfrom
mathieutu:fixes/container-routes

Conversation

@mathieutu
Copy link
Contributor

@mathieutu mathieutu commented Mar 9, 2020

Hi,

This PR fixes laravel/ideas#2114 (no idea why this bug have been moved to ideas, maybe I haven't made me understood 😕)

Context:
When injecting something witch can be null, the \Illuminate\Routing\RouteDependencyResolverTrait::resolveMethodDependencies method doesn't add it to parameters to inject, because it can't difference it from void return.

I've added a default return value, to indicate that we want to strip the value, to allow null value.

  • This PR should not be a breaking change: all tests pass, and the previous behavior was not changed.
  • A test to address this case was added.

You can reproduce the bug with:

class AppServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->bind(Service::class, fn() => null);
    }

    public function boot()
    {
        Route::get('/foo/{id}', function (?Service $service, string $id) {
            // Argument 1 passed ... must be an instance of Service or null, string given.
        });

        Route::get('/not-working', function (?Service $service) {
            // Too few arguments ... 0 passed ... and exactly 1 expected.
        });

        Route::get('/working', function (?Service $service = null) {
            // Working
        });
    }
}

And see the errors thrown:

Thanks.

Matt'

PS: If you read this, and can answer to this https://twitter.com/mathieutu/status/1236997027122249728?s=20, I would like to propose a PR for the router with a quite important breaking change, and so understand why the behavior of Laravel routing is like that, and why it is different from standard one.
Thanks.

@mathieutu
Copy link
Contributor Author

StyleCI's not happy, but I'm not comfortable with the change proposed, as it makes the function not understandable.

-        $container->bind(RoutingTestUserModel::class, function() {
-            return null;
+        $container->bind(RoutingTestUserModel::class, function () {
         });

@mathieutu mathieutu changed the title Fix null value injected from container in routes. [7.x] Fix null value injected from container in routes. Mar 9, 2020
@GrahamCampbell GrahamCampbell changed the title [7.x] Fix null value injected from container in routes. [7.x] Fix null value injected from container in routes Mar 9, 2020
@GrahamCampbell
Copy link
Collaborator

Laravel's code standard is like this because when a fucntion that has no return statement is called and the result is used or assigned to a variable, it is the same as using the value null in its place. The actual return statement can be optimized away.

@deleugpn
Copy link
Contributor

deleugpn commented Mar 10, 2020

I actually tried to fix this about 2 weeks ago and my patch was so bad that I never sent it. This looks like a really good patch with minor code changes to fix a moderate problem.
As someone who failed to find a good solution for this, I can appreciate the nice job you did there.

@mpyw
Copy link
Contributor

mpyw commented Mar 10, 2020

Co-Authored-By: mpyw <ryosuke_i_628@yahoo.co.jp>
@taylorotwell taylorotwell merged commit 4638617 into laravel:7.x Mar 12, 2020
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

Successfully merging this pull request may close these issues.

Null parameter from container is removed when injected in controller.

5 participants