-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[DependencyInjection] Add SubscribedService
attribute, deprecate current ServiceSubscriberTrait
usage
#42238
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
Conversation
796f455
to
9baa209
Compare
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 like this approach - we have decided not to use ServiceSubscriberTrait
in our site because, when trying to introduce it, one dev spent a long time trying to figure out a sudden autowiring error (it was because it was trying to wire a model class due to an unrelated method on the service that we did not want to be considered for the locator).
|
||
if (!$returnType instanceof \ReflectionNamedType) { | ||
// todo, what exception to throw? | ||
throw new \RuntimeException(sprintf('Cannot use "%s" on methods with a union return type in "%s::%s()".', SubscribedService::class, $method->name, self::class)); |
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.
Why ? the previous loop does not have this restriction.
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 treated this as a bug. If the return type is Service1|Service2
, what should be used for the service locator?
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 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.
Yes :). Is there an example of using union/intersection types with ServiceSubscriberInterface
?
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.
The example from the PR was an intersection of two serializer interfaces that would yield the serializer
service, e.g. NormalizerInterface&DenormalizerInterface
, so let's explore that:
class MyService implements ServiceSubscriberInterface
{
use ServiceSubscriberTrait;
private function getSerializer(): NormalizerInterface&DenormalizerInterface
{
return $this->container->get(__METHOD__);
}
}
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.
Yep, I'll try to make that work. I'm looking for what the array returned from ServiceSubscriberInterface::getSubscribedServices()
looks like when using union/intersection.
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 see. We need to come up with a new convention for that, I guess.
To make the trait usable in 5.4 without WTF, we would need a way to opt-in for the new behavior (here, there is nothing that will stop registering other private methods, with no way to avoid the deprecation warning if they are not meant to be subscribed) |
What about deprecating the trait instead? |
What about, if using the attribute on any method, you've opted into the new way and methods without the attribute are ignored? |
And creating a new trait entirely? Suggestions on a new name? |
Well, providing an easy implemention of the |
I was considering deprecating the trait and not replacing it, but if you think we should keep it, no need to create a new one if we can make a nice deprecation layer. |
I personally like this feature so I think we should keep it but I understand it's a bit... controversial (and could be easily abused). If you're ok keeping it, I'll add the nice deprecation layer and finish this PR. Alternatively, if you want to deprecate/remove, I can easily maintain this feature in a 3rd party package. |
I'm fine keeping it now that we have it. |
07877ad
to
fee84f7
Compare
I've updated/added tests and improved the deprecation layer:
|
fee84f7
to
4306aaa
Compare
I could use some direction on fixing the remaining CI errors. |
SubscribedService
attribute, deprecate current ServiceSubscriberTrait
usage
54535f1
to
1cbc600
Compare
Assuming this is still wanted for 5.4, once merged, I'll work on a PR to drop the deprecation layer in 6.0. Still need a bit of direction for fixing the tests. I believe it's a dependency issue, |
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.
ideally tests on DI should work on all versions of contracts, or be skipped on non-supported ones
7afa27c
to
716b275
Compare
716b275
to
a5bb886
Compare
I believe all related tests are now passing. I fixed some pslam issues but don't understand the remaining ones. |
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.
one last non-trivial note :)
throw new \LogicException(sprintf('Cannot use "%s" on methods without a return type in "%s::%s()".', SubscribedService::class, $method->name, self::class)); | ||
} | ||
|
||
$services[$attribute->newInstance()->key ?? self::class.'::'.$method->name] = '?'.$returnType->getName(); |
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.
this should likely do $returnType instanceof \ReflectionNamedType ? ->getName() : (string)
for the last part.
also, when the attribute is used, I'm not sure about the ?
prefix. Shouldn't we add it only when the type is nullable? (and remove |null
from the string representation of the union)
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.
this should likely do $returnType instanceof \ReflectionNamedType ? ->getName() : (string) for the last part.
Like this?
$services[$attribute->newInstance()->key ?? self::class.'::'.$method->name] = '?'.($returnType instanceof \ReflectionNamedType ? $returnType->getName() : $returnType);
I just realized ReflectionType::__toString
is deprecated.. Should we be relying on this?
also, when the attribute is used, I'm not sure about the ? prefix. Shouldn't we add it only when the type is nullable? (and remove |null from the string representation of the union)
Good call, I'll make this change. Should I leave the BC layer as is?
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've made these changes (let me know if you'd like me to backport this to the BC layer).
I'm not sure how to handle union/intersection types. See #42238 (comment).
a5bb886
to
2fa213f
Compare
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.
(with minor comments)
f045e22
to
3cef7b7
Compare
…rrent `ServiceSubscriberTrait` usage
3cef7b7
to
4a7aa8e
Compare
Thank you @kbond. |
Great, once this makes its way into the 6.0 branch, I'll remove the deprecation layer. |
now merged up to 6.0 |
…precation layer (kbond) This PR was merged into the 6.0 branch. Discussion ---------- [DependencyInjection] remove `ServiceSubscriberTrait` deprecation layer | Q | A | ------------- | --- | Branch? | 6.0 | Bug fix? | no | New feature? | no | Deprecations? | no | Tickets | Followup to #42238 | License | MIT | Doc PR | TODO This removes the deprecation layer we added in #42238. Commits ------- 4a6226d [DependencyInjection] remove ServiceSubscriberTrait deprecation layer
This is a fix for #42217 using what I proposed there (adding
SubscribedService
attribute). The current usage is deprecated in 5.4 only when using PHP 8+. I suggest removing the current usage entirely in Symfony 6.0 - this will fully fix the bug.Deprecation Layer:
SubscribedService
attribute, works as it does currently but a deprecation warning is triggered.SubscribedService
attribute, you've opted-into the new functionality (methods w/o the attribute are ignored).