-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[DI] Add and wire ServiceSubscriberInterface - aka explicit service locators #21708
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
@@ -99,6 +99,10 @@ public static function createResourceForClass(\ReflectionClass $reflectionClass) | |||
*/ | |||
protected function processValue($value, $isRoot = false) | |||
{ | |||
if ($value instanceof AutowiredReference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $value->getInvalidBehavior() && $this->container->has((string) $value)) { |
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.
shouldn't it be AutowirableReference
?
|
||
$serviceMap = array(); | ||
|
||
foreach ($services as $services) { |
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.
$services
looks undefined here
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.
Plus, the array and the item are the same variable, I don't think this is wanted.
throw new InvalidArgumentException(sprintf('%s::getSubscribedServices() must return types as non-empty strings for service "%s" key "%s", "%s" returned.', $class, $this->currentId, $key, gettype($type))); | ||
} | ||
if ($isOptional = '?' === $type[0]) { | ||
$type = substr($type, 1); |
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.
shouldn't you validate that the type is still not empty here ? ``?```alone should be forbidden too.
|
||
namespace Symfony\Component\DependencyInjection; | ||
|
||
Psr\Container\ContainerInterface; |
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.
missing use
@@ -21,7 +23,7 @@ | |||
* | |||
* @experimental in version 3.3 | |||
*/ | |||
class ServiceLocatorArgument implements ArgumentInterface | |||
class ServiceLocatorArgument extends Definition implements ArgumentInterface |
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.
won't this cause issues with recursive passes processing Definition objects ? Is it really a Definition ?
Talking with others, it looks like this approach has a drawback: it does not play well with composition. |
return new Reference($this->serviceLocator); | ||
} | ||
|
||
if (!$value instanceof Definition || $value->isAbstract() || $value->isSynthetic() || !$value->hasTag('kernel.service_subscriber')) { |
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.
should be added to UnusedTagsPass::$whitelist
b5ab5d1
to
6c8f067
Compare
a887059
to
040df3d
Compare
PR rebased and ready Status: needs review |
f5cfdf0
to
70cc3c5
Compare
Just added a few more test cases. |
As you can see, this allows having type-hinted service locators also, on top of explicit deps. |
5e30b79
to
8f830e6
Compare
8f830e6
to
0d917b3
Compare
0d917b3
to
c5e80a2
Compare
|
||
foreach ($value->getTag('container.service_subscriber') as $attributes) { | ||
if (!$attributes) { | ||
continue; |
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.
Shoudn't we throw an exception 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.
When there is not attributes at all, L75 creates "TypedReference" that target the service that has the same name as the type
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 @nicolas-grekas. |
return array( | ||
'routing.loader' => LoaderInterface::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.
@nicolas-grekas The service definition has not been updated (not tagged container.service_subscriber
) so this is actually unused, is it expected?
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.
Expected: getParameter is used, so cannot by a PSR11 container.
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 ok, I was wondering if you still did it on purpose.
This PR implements the second and missing part of #20658: it enables objects to declare their service dependencies in a similar way than we do for EventSubscribers: via a static method. Here is the interface and its current description:
We could then have eg a controller-as-a-service implement this interface, and be auto or manually wired according to the return value of this method - using the "kernel.service_subscriber" tag to do so.
eg:
The benefits are:
Some might argue that: