Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[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

Merged
merged 1 commit into from
Oct 3, 2018

Conversation

codedmonkey
Copy link
Contributor

@codedmonkey codedmonkey commented Sep 23, 2018

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).

Copy link
Member

@nicolas-grekas nicolas-grekas left a 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)) {
Copy link
Member

@nicolas-grekas nicolas-grekas Sep 23, 2018

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]);
Copy link
Member

@nicolas-grekas nicolas-grekas Sep 24, 2018

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

Copy link
Contributor Author

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.

Copy link
Member

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.


$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')));
Copy link
Member

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;
Copy link
Member

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 ?

Copy link
Member

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?

Copy link
Member

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

Copy link
Member

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.

Copy link
Contributor Author

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.

$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));
Copy link
Member

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.

Copy link
Member

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 :) )

Copy link
Contributor Author

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.

Copy link
Member

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));

Copy link
Contributor Author

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.

@nicolas-grekas
Copy link
Member

Thanks for the update. Can you add a test case that throws the new exception please?

@codedmonkey
Copy link
Contributor Author

I removed the additional exception if that's all right with you?

@nicolas-grekas
Copy link
Member

Thank you @codedmonkey.

@nicolas-grekas nicolas-grekas merged commit 1c1210a into symfony:master Oct 3, 2018
nicolas-grekas added a commit that referenced this pull request Oct 3, 2018
…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
@nicolas-grekas nicolas-grekas modified the milestones: next, 4.2 Nov 1, 2018
@fabpot fabpot mentioned this pull request Nov 3, 2018
@fabpot fabpot mentioned this pull request Nov 3, 2018
@codedmonkey codedmonkey deleted the service-locator branch December 14, 2018 23:26
javiereguiluz added a commit to symfony/symfony-docs that referenced this pull request Sep 23, 2019
…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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants