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

Skip to content

[DI] Allow to choose an index for tagged collection #29598

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

Closed

Conversation

deguif
Copy link
Contributor

@deguif deguif commented Dec 13, 2018

Q A
Branch? master
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? tbd
Fixed tickets #29203
License MIT
Doc PR symfony/symfony-docs#tbd

Add a way to specify an index based on a tag attribute when injecting a tag collection into services, but also a a way to fallback to a static method on the service class.

!tagged {name: 'tag_name', index_by: 'tag_attribute_name', default_index_method: 'static_method'}

Tasks

  • Support PHP loader
  • Support YAML loader
  • Support XML loader (update XSD)
  • Add tests

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.

really nice :) This will work for iterators. The next step would be to make it work for locators also, using eg:
!service_locator !tagged {name: foo, index_by: bar}

if (\is_string($argument) && $argument) {
return new TaggedIteratorArgument($argument);
} elseif (\is_array($argument) && isset($argument['name']) && $argument['name']) {
return new TaggedIteratorArgument($argument['name'], $argument['index_by'] ?? null, $argument['default_index_method'] ?? null);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to ease spotting typos, we should validate that there are no extra keys

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

continue;
}

if (null === $defaultIndexMethod) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when no $defaultIndexMethod is provided, we should imho derivate a conventional one from the attribute name.
My suggestion would be to camel-case the attribute name "foo_bar" and build something like "getDefaultFooBarName":
$defaultIndexMethod = 'getDefault'.str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $indexAttribute))).'Name';

Copy link
Contributor Author

@deguif deguif Dec 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see the interest in the default method fallback.
But how can be handled the fact that sometime I don't want to fallback on a method and always require a tag attribute to be defined, should I pass an empty string eg. '' to handle this case?

For example: !tagged {name: 'tag_name', index_by: 'tag_attribute', default_index_method: ''}

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 this use case exists. Why would a tagged iterator care? That's not its job 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.

Ok what you mean, is that there should always be a fallback method, and this fallback method is by default auto generated from the above strategy.
What I can do is only override this default by providing one explicitly?

Copy link
Member

@nicolas-grekas nicolas-grekas Dec 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

correct - in case the convention doesn't suit you

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Behaviour is now updated

@nicolas-grekas nicolas-grekas changed the title Allow to choose an index for tagged collection [DI] Allow to choose an index for tagged collection Dec 14, 2018
@deguif deguif force-pushed the custom-indexable-tagged-iterator branch from a2041eb to b750077 Compare December 14, 2018 16:24
{
$services = array();

if (null === $indexAttribute && null !== $defaultIndexMethod) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this really required? i might want to "key by method" as a default approach

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is: one must have a way to configure the key they want using configuration. The command example is again enlightening: it must be possible to ignore the default command name and let configuration take over the real command name. Same here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i figured :)

@ro0NL
Copy link
Contributor

ro0NL commented Dec 14, 2018

alternatively

!tagged
  name: tag_name,
  index_by: null | attribute_or_method_name
  is_method: true | false

if index_by is null we follow the convention mentioned above to find a default method (is_method=true).

@nicolas-grekas
Copy link
Member

@ro0NL nope, really, see above comment.

@ro0NL
Copy link
Contributor

ro0NL commented Dec 14, 2018

Wait, got ya ... an alias attribute locally overrides Class::getAliasName() 👍

@deguif deguif force-pushed the custom-indexable-tagged-iterator branch from b750077 to 1b5b1f8 Compare December 14, 2018 17:35
@deguif deguif force-pushed the custom-indexable-tagged-iterator branch 2 times, most recently from 5006043 to f40903e Compare January 18, 2019 11:18
@kunicmarko20
Copy link

This is exactly what I am looking for, is it possible to have some kind of fallback and use class name for index_by?

@nicolas-grekas
Copy link
Member

@kunicmarko20 the fallback exists: create

public static function getDefaultMyThingName()
{
    return static::class;
}

the static method covers all use cases and reduces complexity, no need for anything else IMHO.

@kunicmarko20
Copy link

It isn't really a fallback if I have to create a method and return the class name, but at least better than me creating compiler pass all the time, thank you! great addition!

@deguif deguif force-pushed the custom-indexable-tagged-iterator branch from f40903e to 2b54bec Compare February 8, 2019 14:22
@deguif deguif force-pushed the custom-indexable-tagged-iterator branch from 2b54bec to 17d9fae Compare February 8, 2019 14:24
@nicolas-grekas
Copy link
Member

Continued in #30257, thanks @deguif !

nicolas-grekas added a commit that referenced this pull request Feb 22, 2019
…ged collection (deguif, XuruDragon)

This PR was merged into the 4.3-dev branch.

Discussion
----------

[DependencyInjection] Allow to choose an index for tagged collection

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #29203
| License       | MIT
| Doc PR        | symfony/symfony-docs#11009

This is the continuity of the PR #29598

Add a way to specify an index based on a tag attribute when injecting a tag collection into services, but also a a way to fallback to a static method on the service class.

```yaml
services:
  foo_service:
    class: Foo
    tags:
      - foo
  foo_service_tagged:
    class: Bar
    arguments:
      - !tagged
          tag: 'foo'
          index_by: 'tag_attribute_name'
          default_index_method: 'static_method'
```
```xml
<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
  <services>
    <service id="foo" class="Foo">
        <tag name="foo_tag" />
    </service>
    <service id="foo_tagged_iterator" class="Bar" public="true">
      <argument type="tagged" tag="foo_tag" index-by="tag_attribute_name" default-index-method="static_method" />
    </service>
  </services>
</container>
```

Tasks

* [x]  Support PHP loader/dumper
* [x]  Support YAML loader/dumper
* [x]  Support XML loader/dumper (and update XSD too)
* [x]  Add tests
* [x]  Documentation

Commits
-------

101bfd7 [DI] change name to tag + add XMl support + adding yaml/xml tests
845d3a6 Allow to choose an index for tagged collection
@nicolas-grekas nicolas-grekas removed this from the next milestone Apr 30, 2019
@nicolas-grekas nicolas-grekas added this to the 4.3 milestone Apr 30, 2019
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.

6 participants