-
Notifications
You must be signed in to change notification settings - Fork 11.1k
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.7] [Option 1] Improve PSR-11 implementation #25870
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please fix the tests and StyleCI checks?
I think this |
The try catch is a must-have anyway as PSR-11 specifies that |
In general, if the container does not define the object, |
PSR-11 disagrees with you. |
PSR-11 says this about the
Since Laravel's container has such great autowiring abilities there is no reason why the |
IMO "get" is pretty straightforward. An item is fetched from the container. Autowiring "makes" an object. This seems outside the scope of psr-11. Which is why it is left up to the framework. Some containers handle autowiring differently, however, unless there is an "identifier" stored on the container explicitly, "get" doesn't seem to apply. Seems like a nightmare of maintenance to make this work properly and address all of the edge cases |
This is great feedback for PSR editors, which is beyond the scope of this PR. According to their statement, it's the container implementation's job to decide whether to do auto-wire for @moufmouf said:
Perhaps @weierophinney and @mnapoli might also be interested on the feedback about how people have a resistence of having |
@deleugpn I don't agree that PSR-11 only allows for answering the first two of the four distinctions you made. Containers can autowire, but for those consuming the container, that is an implementation detail. Ideally, if autowiring is in place, In zend-servicemanager, we have the concept of "abstract factories". These are factories that can produce zero or more instances, and the interface for these includes a method for testing if it can produce the requested instance. Abstract factories therefor provide us with autowiring, and allow our container to answer the last two of the bullet points you noted. (In point of fact, since version 3, zend-di now provides an abstract factory that can be consumed by zend-servicemanager, allowing it to provide reflection-based autowiring for any service!) So, that's my long-winded way of saying I agree with @moufmouf here. It would be a good idea for you to look at other PSR-11 implementations as you do this sort of work, as it can allow you to see how others have tackled the problem. I think you would have found early that most of them provide some way of autowiring. |
@weierophinney I agree that PSR-11 can answer all 4. It's just current Laravel implementation (without this PR) that only answer the first 2. I'm trying to change that. |
Reading the PSR-11 spec:
There is no language there about if the container could hypothetically resolve some unknown class. It only states that that we should return a boolean value indicating if the identifier is known to us. Something is not explicitly bound to the container is not known to us. We may be able to resolve it, we may not be able to. We don't KNOW if we can until we actually try it (or recursively reflect through every dependency down the chain) - and if we don't know until we try it, what is the point of the I don't want to get deep into knocking on PSR-11 here but with an auto-wiring container that can resolve things that aren't explicitly bound, the I guess I basically agree with the implementation you have here. |
@deleugpn were you planning to change the functionality of |
@taylorotwell I agree with your reasoning here. Although the PSR text doesn't say it, the editors have been saying that The approach on this PR is different, though, we can just ignore the existence of The problem with Laravel right now is that |
I agree with @deleugpn here. Thank you for pushing this forward. And thanks for your patience on it 👍 . |
So, is this a breaking change? |
AFAIK it's not since you are throwing the same exception if the object is bound? |
Note that the container now does not follow the PSR-11 spec since the spec (IMO a poor idea) states that |
Mmh I have to agree with you considering your use case, it would have been better not to include that sentence I guess. |
Just for reference: Another reason for the In an auto-wiring, non-composite container, |
I've recently tried to implement a small lib to bridge between a Laravel app and a legacy app and I finally understood why so many people tried to change the PSR-11 implementation, which frankly I got it quite wrong. Ref #25682, #25678, #21335, #21327, #19822 and laravel/ideas#803.
The Method
Let's look at the possibilities of
$container->get($identifier);
call.1-
$identifier
has been explicitly bound and the container can resolve it.2-
$identifier
has been explicitly bound and the container cannot resolve it.3-
$identifier
has not been explicitly bound, but the container can resolve it.4-
$identifier
has not been explicitly bound and the container cannot resolve it.The Problem
Right now, only option 1 and 2 works when using PSR-11 with Laravel container. Something has to explicitly bind into the Laravel container in order for it to work. If it was never bound before, it will not try to do anything. PSR-11 doesn't offer any way to bind things into the container, only resolve out of it.
The Proposal
By making
has
an alias ofresolve / make
, we cover all 4 scenarios withget
.1- It will resolve explicitly bound into their concrete.
2- It will throw
ContainerExceptionInterface
when trying to resolve explicitly bound into their concrete.3- It will try to resolve non-explicitly bound (auto-wire).
4- It will fail to resolve anything non-resolvable.
The Usage
If this patch gets applied, package developers can opt to ignore the
has
method and use Laravel container as follow:or even