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

[5.6] Improve allowed method injection parameters #24234

Merged
merged 1 commit into from May 24, 2018

Conversation

Projects
None yet
7 participants
@mpociot
Contributor

mpociot commented May 16, 2018

This PR adds the ability to pass a specific object instance to a method called from the container, regardless of the parameter name.

This can be useful in situations where you want to inject a specific object instance into a method call, no matter what name that parameter has.

@freekmurze

This comment has been minimized.

Show comment
Hide comment
@freekmurze

freekmurze May 16, 2018

Contributor

Pretty sweet, and exactly what I need for some stuff I'm working on 😄

Contributor

freekmurze commented May 16, 2018

Pretty sweet, and exactly what I need for some stuff I'm working on 😄

@nunomaduro

This comment has been minimized.

Show comment
Hide comment
@nunomaduro

nunomaduro May 16, 2018

Contributor

Seems pretty nice to me. 👍

Contributor

nunomaduro commented May 16, 2018

Seems pretty nice to me. 👍

@sisve

This comment has been minimized.

Show comment
Hide comment
@sisve

sisve May 17, 2018

Contributor
  1. It looks like only the first matching parameter of the specified type will be matched. Is this intentional?
  2. How do you handle the weird cases of conflicts where a parameter name also happens to match a class name? The syntax is identical to the caller...
Contributor

sisve commented May 17, 2018

  1. It looks like only the first matching parameter of the specified type will be matched. Is this intentional?
  2. How do you handle the weird cases of conflicts where a parameter name also happens to match a class name? The syntax is identical to the caller...
@mpociot

This comment has been minimized.

Show comment
Hide comment
@mpociot

mpociot May 17, 2018

Contributor

@sisve

  1. It looks like only the first matching parameter of the specified type will be matched. Is this intentional?

Yeah that's correct. I'm not sure if we need to handle this logic. Until now, it wasn't possible to override specific hinted classes with method injection, so the case that someone needs to override two specific instances of the same class in combination with method injection could be quite rare.

  1. How do you handle the weird cases of conflicts where a parameter name also happens to match a class name? The syntax is identical to the caller...

Do we need to handle this extreme edge case?

The same edge case occurs right now when using the call method with a parameter that's also a class name that could be resolved from the container.

Contributor

mpociot commented May 17, 2018

@sisve

  1. It looks like only the first matching parameter of the specified type will be matched. Is this intentional?

Yeah that's correct. I'm not sure if we need to handle this logic. Until now, it wasn't possible to override specific hinted classes with method injection, so the case that someone needs to override two specific instances of the same class in combination with method injection could be quite rare.

  1. How do you handle the weird cases of conflicts where a parameter name also happens to match a class name? The syntax is identical to the caller...

Do we need to handle this extreme edge case?

The same edge case occurs right now when using the call method with a parameter that's also a class name that could be resolved from the container.

@taylorotwell

This comment has been minimized.

Show comment
Hide comment
@taylorotwell

taylorotwell May 21, 2018

Member

If you already know the function needs that instance... couldn't you have done...

function () use ($stub) {}
Member

taylorotwell commented May 21, 2018

If you already know the function needs that instance... couldn't you have done...

function () use ($stub) {}
@taylorotwell

This comment has been minimized.

Show comment
Hide comment
@taylorotwell
Member

taylorotwell commented May 23, 2018

Ping @mpociot

@mpociot

This comment has been minimized.

Show comment
Hide comment
@mpociot

mpociot May 23, 2018

Contributor

@taylorotwell I don't quite understand what you mean. Could you explain it some more?

I want to be able to inject a specific object instance using method injection, but I have no idea what's the name of the parameter - I only know the type-hinted class.

For example, if you're developing a package that needs to inject a specific instance into a method, the only way to do it right now, is to tell people how they need to name the method properties.

Then we could pass an array of parameters with this exact parameter name.

With this PR, we would be able to say: Just typehint this class and it will be injected automatically and pass the parameters with the fully qualified class name - just like I did in the added test.

Contributor

mpociot commented May 23, 2018

@taylorotwell I don't quite understand what you mean. Could you explain it some more?

I want to be able to inject a specific object instance using method injection, but I have no idea what's the name of the parameter - I only know the type-hinted class.

For example, if you're developing a package that needs to inject a specific instance into a method, the only way to do it right now, is to tell people how they need to name the method properties.

Then we could pass an array of parameters with this exact parameter name.

With this PR, we would be able to say: Just typehint this class and it will be injected automatically and pass the parameters with the fully qualified class name - just like I did in the added test.

@sisve

This comment has been minimized.

Show comment
Hide comment
@sisve

sisve May 23, 2018

Contributor

@mpociot Would it make sense to implement that as a parent/child container? Where a child container would forward unknown resolve attempts to the parent container. This would also solve scenarios where a dependency of a dependency of a dependency were to resolve the contract, instead of just the method you're calling.

$childContainer = new Container($parentContainer);
$childContainer->bind(Contract::class, Implementation::class);
$myClass = $childContainer->call([$myService, 'myMethod']);
Contributor

sisve commented May 23, 2018

@mpociot Would it make sense to implement that as a parent/child container? Where a child container would forward unknown resolve attempts to the parent container. This would also solve scenarios where a dependency of a dependency of a dependency were to resolve the contract, instead of just the method you're calling.

$childContainer = new Container($parentContainer);
$childContainer->bind(Contract::class, Implementation::class);
$myClass = $childContainer->call([$myService, 'myMethod']);

@taylorotwell taylorotwell merged commit 49549b7 into laravel:5.6 May 24, 2018

2 checks passed

continuous-integration/styleci/pr The analysis has passed
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
@TBlindaruk

This comment has been minimized.

Show comment
Hide comment
@TBlindaruk

TBlindaruk May 24, 2018

Contributor

@taylorotwell ,should be documentation update?

If yes, @mpociot could you update the documentation?

Contributor

TBlindaruk commented May 24, 2018

@taylorotwell ,should be documentation update?

If yes, @mpociot could you update the documentation?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment