framework: [5.0] Contextual binding doesn't work with method injection.
Right now contextual binding resolution only works at the constructor level but it should also work with method injection. So, for example, if we have:
$app->when('PostsController')
->needs('PostRepositoryInterface')
->give('EloquentPostRepository');
then PostsController::__construct(PostRepositoryInterface $posts) will resolve the dependency correctly but PostsController::store(PostRepositoryInterface $posts) will only look for a non-contextual binding and will fail to resolve.
About this issue
- Original URL
- State: closed
- Created 10 years ago
- Reactions: 6
- Comments: 33 (8 by maintainers)
+1 I would love to use contextual binding in a job’s
handle()method.@redgenie for 2 months I did not work with laravel, but if you want some real example about contextual binding in laravel ( >5), you can refer this article http://longkyanh.info/blog/2016/04/29/contextual-binding-in-laravel-and-o-in-solid-principles/
It would be great to have something like this.
You can do it easily with
bindMethodExample:
AppServiceProvider.php
+1 I would like to see contextual binding -
when->needs->giveworking on controllers too. I think it is a valid use case @taylorotwell. Thanks for bringing this up @smallhadroncollider.I also posted the same question on Stack Overflow.
Consider the following scenario, which is what I’m currently using for my project’s API:
I have a base API controller which implements the CRUD functionalities for various entities (e.g. User, Address, Phone, etc.).
As a simplified example, here is the code for the base controller:
Each entity’s controller (e.g.
UsersController) would extend the base controller, inheriting the CRUD functionalities. In the above, I’m using contextual bindings to inject the relevant repository into the__constructor()method (e.g. whenUsersControllerneedsRepositoryInterface, giveUserRepository). It works beautifully for theindex(),show()anddelete()methods.In order to implement
store()andupdate()methods, I would need to inject object for the relevant request class (I have one for create and one for update operation, for each entity).The problem is, I cannot inject object of the relevant request class into the constructor due to a couple of reasons:
index()method!). This is clearly wrong, and validation would obviously fail forindex(),show()anddelete()methods, since no user input is supplied for them.store()orupdate()) being run. This cannot be achieved using constructor injection.If contextual binding also worked for controller methods other than the constructor, I could just inject the relevant request object directly into the method. For example, I could do something like the following:
Since this doesn’t work as of now, I’m using a workaround by declaring a couple of properties
$createRequestClassand$updateRequestClass, which I override in children controllers to the relevant request classes. Then, within thestore()andupdate()methods, I manually create the instance of the relevant request class using something like$request = App::make($this->createRequestClass).If contextual bindings would have worked for methods, even this bit of code would not be been needed and everything would have been beautiful 😃
Can you please add a real-life example where you need different implementations of the same parent type injected in different methods of the same class? Thanks!
@reyezstef I found a work around solution for this, hope this help
+1 Not only in controllers but it would be very useful in some Jobs for example. Jobs rely on the injection only in the handle() method. Sometimes, you might want to give different instances of the interface to different jobs.
@smallhadroncollider @hannesvdvreken
I have the same issue. use
bind()works, but usewhen->needs->givenot workingI can’t get this to work.
The following works (but isn’t useful):
This does not:
@robinmitra Hi! Is it working? Because I have the same issue.
Why was this silently closed without further discussion?