-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[DI] Implement PSR-11 #21265
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
[DI] Implement PSR-11 #21265
Conversation
@@ -21,7 +22,7 @@ | |||
* @author Fabien Potencier <[email protected]> | |||
* @author Johannes M. Schmitt <[email protected]> | |||
*/ | |||
interface ContainerInterface | |||
interface ContainerInterface extends PsrContainerInterface |
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.
I chose to have ContainerInterface
extend PsrContainerInterface
, so that any interface is marked as psr-compliant. Not sure it is the right thing to do though, because php cannot enforce all the contracts defined in the interface docs (like what exception to throw when). Tell me if you feel I should remove this and add implements ContainerInterface
in the main implementation.
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.
If it works for PHP, fine.
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.
that basically means in whole framework you will not use Psr
version, but Symfony
version.
Then, one will be able to use concrete class that implements Symfony
version as parameter for method expecting Psr
version, but not the other way around. So, if I will have some package that follows Psr
, I won't be able to use it directly in Symfony project, because everywhere the framework will require Symfony
version instead
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.
everywhere the framework will require Symfony
Not sure I get what you mean, but IMO once this is merged, we should hunt for the Symfony
version everywhere, see what calls are made there, and if we can replace use Psr
version as type hinting there.
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.
@greg0ire without breaking BC, with the benefit of reducing the feature-set for the shake of PSR11 compliance? I doubt this is ever going to happen...
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.
@jvasseur yes it does
the issue is that $foo instanceof A
implies that calling $foo->test($anotherInstanceOfA)
is allowed.
Since $anInstanceofB instanceof A
, calling $anInstanceofB->test($anotherInstanceOfAButNotB)
must thus be allowed.
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.
So… I found a bug in php?
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.
It's a know limitation of the PHP engine : https://bugs.php.net/bug.php?id=69612#1431343525
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.
But your example is wrong anyway, functions parameters could be contravariant (they are invariant in PHP) meaning they can accept a wider type. In your example they are covariant instead.
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.
Oh you're right, my logic was wrong indeed! Which means this would indeed be a BC-break, sorry I got confused.
/** | ||
* Base InvalidArgumentException for Dependency Injection component. | ||
* | ||
* @author Bulat Shakirzyanov <[email protected]> | ||
*/ | ||
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface | ||
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface, ContainerException |
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.
EnvNotFound
extends this exception, so no need to add implementation declaration in it.
About "the mandatory NotFoundExceptionInterface on non-existing service problem", throwing an exception on missing service id is optional in the current implementation while mandatory in the PSR. How should we solve this problem? I was thinking we could deprecate the second argument of |
9adc7ca
to
0d62fdc
Compare
@@ -16,7 +16,8 @@ | |||
} | |||
], | |||
"require": { | |||
"php": ">=5.5.9" | |||
"php": ">=5.5.9", | |||
"psr/container": "^1.0@dev" |
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.
add also provide section https://getcomposer.org/doc/04-schema.md#provide , like in https://github.com/Seldaek/monolog/blob/master/composer.json#L52-L54
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.
See TODO list ;) , I'm not sure to be able to implement it perfectly, so first, let's get as close as we can without a BC-break.
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.
Still please add it.
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.
Fine 👍
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.
Looks like it should also be added to the root composer.json
.
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.
Uuuuh… it's already there, isn't it?
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.
Indeed... I missed it 😳
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.
Thanks for reviewing anyway :)
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.
There is no issue with throwing : the PSR standardize only one argument, and says to throw. Fortunately that's the default behavior so anyone using the container in the PSR11 way will have it work as expected.
When the 2nd argument is used, we're not in PSR11 anymore, thus we can behave as we want.
@@ -21,7 +22,7 @@ | |||
* @author Fabien Potencier <[email protected]> | |||
* @author Johannes M. Schmitt <[email protected]> | |||
*/ | |||
interface ContainerInterface | |||
interface ContainerInterface extends PsrContainerInterface |
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.
If it works for PHP, fine.
@@ -16,7 +16,8 @@ | |||
} | |||
], | |||
"require": { | |||
"php": ">=5.5.9" | |||
"php": ">=5.5.9", | |||
"psr/container": "^1.0@dev" |
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.
Still please add it.
0d62fdc
to
f8bf6ea
Compare
Makes sense. We can't hurt people that don't know which implementation they are using, because if they don't they will probably not risk calling |
f8bf6ea
to
00a8126
Compare
composer.json
Outdated
@@ -20,6 +20,7 @@ | |||
"doctrine/common": "~2.4", | |||
"twig/twig": "~1.28|~2.0", | |||
"psr/cache": "~1.0", | |||
"psr/container": "^1.0@dev", |
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.
Just reminder comment: Remove @dev
annotation when the package will be stable.
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 we remove it now so that this PR is ready to be merged?
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.
fixed
👍 the interface was designed to be compatible with Symfony's default behavior when called with the PSR signature. |
I did not read the underlying discussions for this spec but there definitely was a "well this is convenient" feeling when implementing it in Symfony 😄 |
It looks only small changes are required, nice! |
00a8126
to
62c61ef
Compare
@dunglas yup, that was a breeze :) |
RuntimeException also isn't it? |
Why not make ExceptionInterface extend Psr\Container\ContainerExceptionInterface? |
Only exceptions thrown directly by the container are supposed to implement this, so I only applied it to exceptions listed here This means this is an issue doesn't it ? Should I change this line so that the exception thrown here is wrapped into another? |
Can't find it in Container.php, so no. |
I suggest to play simpe here. We don't care to add the interface on all exceptions. This wouldn't hurt. |
Yeah but :
What does "directly" mean here? |
I don't know in fact, and that's a good question! |
Very true, plus, less code, so… I'll change that. @mnapoli , can you advise about the meaning of "directly" here though? You know, for science? |
62c61ef
to
ff1b247
Compare
There. The diff is tiny now :) |
@nicolas-grekas what about this? Any thoughts? |
👍 |
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.
👍
Thank you @greg0ire. |
This PR was merged into the 3.3-dev branch. Discussion ---------- [DI] Implement PSR-11 TODO: - [x] wait for a stable version of the psr/container package; - [x] ~~deprecate instanciating ServiceNotFoundException directly, or using any of its methods directly;~~ not relevant anymore - [x] act on the outcome of php-fig/container#8 (solved in php-fig/container#9) ; - [x] ~~solve the mandatory NotFoundExceptionInterface on non-existing service problem (with a flag ?);~~ non-issue, see comments below - [x] provide meta-package psr/container-implementation if all problems can be solved. | Q | A | ------------- | --- | Branch? | master | New feature? | yes | BC breaks? | not at the moment | Tests pass? | didn't pass before pushing, or even starting to code, will see Travis | License | MIT | Doc PR | TODO This PR is a first attempt at implementing PSR-11, or at least trying to get closer to it. Delegate lookup is optional, and thus not implemented for now. Commits ------- bde0efd Implement PSR-11
Thanks for merging! |
Can you please consider BC breaks not only with respect to "implementation" but also to "declaration"?
And that's what happened:
Your interfaces are your burden as much as your implementation. |
@allflame can't reproduce : https://3v4l.org/gNuOY |
@greg0ire you have to change the order of the implemented interfaces : https://3v4l.org/032Sk It's a know PHP bug. EDIT: here is the bugs.php.net reference : https://bugs.php.net/bug.php?id=63816 |
Oh ok... well sorry, but I didn't know that bug. |
Which class should be affected by that? This PR did not change any class to implement two interfaces, did it? |
@xabbuh classes outside Symfony that happen to implement |
Hm yeah, nothing we can account for here. This needs to be changed in those projects or fixed in PHP. |
@xabbuh this "bug" is like 5 years old and since it just a consequence of OOP implementation in PHP it won't likely be "fixed" for another 5 years. My message here is the following: changes in "contracts/definitions" (that is interfaces, inheritance, function declaration etc) have way more potential to break things than changes in the "implementation" (e.g. actual code) |
Well, this means that we would have to avoid providing a PSR-11 compliant container because someone might have already built an external project implementing both PSR-11 and our interface ? This means we would never be able to implement PSR on existing code outside major versions. Btw, our BC promise explicitly mentions that we don't ensure BC if you add new methods in a child class (as this would then forbid us to add any method in our existing classes due to potential signature mismatches for the child class using the name already). Adding extra interfaces on the class generally involve adding such method (PSR-11 actually may not need it though) |
@stof Yes, this is what software versioning, BC and PHP imply. |
Well, are you actually implementing the Symfony ContainerInterface from scratch without using our base classes ? |
No, of course not. |
TODO:
deprecate instanciating ServiceNotFoundException directly, or using any of its methods directly;not relevant anymoresolve the mandatory NotFoundExceptionInterface on non-existing servicenon-issue, see comments belowproblem (with a flag ?);
be solved.
This PR is a first attempt at implementing PSR-11, or at least trying to get closer to it.
Delegate lookup is optional, and thus not implemented for now.