-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[DependencyInjection] Improve ServiceLocatorTagPass service matching #28571
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
831ebf6
to
e58293b
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.
thanks, do you think you could add some tests please?
} | ||
|
||
foreach ($arguments[0] as $k => $v) { | ||
if ($v instanceof ServiceClosureArgument) { | ||
continue; | ||
} | ||
|
||
if (\is_string($type = $v) && preg_match('/^\??[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+$/', $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.
this will allow <argument>Psr\Logger\LoggerInterface</argument>
alongside with <argument type="service" id="Psr\Logger\LoggerInterface" />
I read too fast this part of your proposal. I think it's not a good idea. It would create an inconsistency in the way the configuration works.
But being able to omit the "key" part looks like a good idea to me.
} | ||
|
||
if (\is_int($k)) { | ||
unset($arguments[0][$k]); |
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'd suggest moving "unset" outside of the "if": that will allow preserving the order in the list
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 agree but right after the for loop it does a ksort
so I presume that's unnecessary.
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 forgot about it, no need then. Thanks.
0357dc0
to
55e1075
Compare
|
||
$this->assertEquals(CustomDefinition::class, \get_class($locator('bar'))); | ||
$this->assertEquals(CustomDefinition::class, \get_class($locator('baz'))); | ||
$this->assertEquals(CustomDefinition::class, \get_class($locator('some.service'))); |
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.
assertSame
if (\is_int($k)) { | ||
unset($arguments[0][$k]); | ||
|
||
$k = (string) $v; |
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 we check whether this key already exists in the configured arguments ?
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'm not sure: if the key exists after the numbered one, it will override it - and if it came before, then the numbered one should win to me. works for you also?
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.
nope, it will always override it here. If it comes after the numbered one, processing it will see the value set by the processing of the numbered one, not the original one, as it would have been replaced
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.
Really? foreach operates on a copy of array so that it will yield the original value at this iteration, and overwrite the value set by the numbered step to me.
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.
Added some basic tests that should confirm @nicolas-grekas description. I do like the idea of preventing unexepected behavior for the user but it works either way for me.
a467c0a
to
d44c37f
Compare
$k = (string) $v; | ||
|
||
if (isset($arguments[0][$k])) { | ||
throw new InvalidArgumentException(sprintf('Invalid definition for service "%s": service key "%s" cannot be inherited from the service definition because the key already exists.', $this->currentId, $k)); |
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.
Per my comments above, I'm not sure about this. It should be removed to me.
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 please add tests showing that the later wins over the former if you can, that'll help prove who is right 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.
Fine by me if all differences have been set aside. I've checked how the different configuration formats handled duplicate declarations and they don't seem work the same at all, so there doesn't seem to be a best way.
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 elaborate? What's the difference you spotted?
If we want to keep the exception (I'm fine with it also), I'd suggest a message like:
`Invalid service locator definition for "%s": key "%s" is defined twice.', $this->currentId, $k));
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.
Here's my examples:
// PHP - Result: service_b
->setArguments([[
'service_a' => new Reference('service_a'),
'service_a' => new Reference('service_b'),
]])
// YAML - Result: service_a
arguments:
-
service_a: '@service_a'
service_a: '@service_b'
// XML - Result: service_b
<argument type="collection">
<argument type="service" id="service_a" key="service_a" />
<argument type="service" id="service_b" key="service_a" />
</argument>
Not that how PHP handles duplicate array keys matters a lot, just thought it might give a direction for the right solution.
d44c37f
to
2d6050e
Compare
Thanks for the update. Can you add a test case that throws the new exception please? |
I removed the additional exception if that's all right with you? |
2d6050e
to
1c1210a
Compare
Thank you @codedmonkey. |
…rvice matching (codedmonkey) This PR was squashed before being merged into the 4.2-dev branch (closes #28571). Discussion ---------- [DependencyInjection] Improve ServiceLocatorTagPass service matching | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #26892 | License | MIT | Doc PR | symfony/symfony-docs#10397 Allows omitting of keys for service locator arguments (it will automatically take over the original definition alias). Commits ------- 1c1210a [DependencyInjection] Improve ServiceLocatorTagPass service matching
…tor changes (codedmonkey, javiereguiluz) This PR was submitted for the master branch but it was merged into the 4.3 branch instead (closes #10397). Discussion ---------- [DependencyInjection] Add documentation for service locator changes Adds documentation for PR symfony/symfony#28571 Commits ------- 8d8c65e Reword bc5ef85 [DependencyInjection] Add documentation for service locator changes
Allows omitting of keys for service locator arguments (it will automatically take over the original definition alias).