Skip to content

[DI] Improve PSR4-based service discovery #23986

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
wants to merge 1 commit into from
Closed

[DI] Improve PSR4-based service discovery #23986

wants to merge 1 commit into from

Conversation

kbond
Copy link
Member

@kbond kbond commented Aug 25, 2017

Q A
Branch? master
Bug fix? no
New feature? yes
BC breaks? no (?)
Deprecations? no
Tests pass? yes
Fixed tickets #22397
License MIT
Doc PR todo

This is an attempt to add the feature described here: #22397 (comment). A side effect of my implementation is the namespace is no longer required as the service id - it can be anything now... I am unsure if this is desired or could cause a BC break but all the tests pass (except one testing for an invalid namespace).

With this feature, you can now define services like this:

services:
    command_handlers:
        resource: ../../src/Domain/*/CommandHandler
        tags: [command_handler]

    event_subscribers:
        resource: ../../src/Domain/*/EventSubscriber
        tags: [event_subscriber]

Let me know if you have alternative suggestions for how to implement this.

(ping @nicolas-grekas)

*
* @link http://jarretbyrne.com/2015/06/197/
*/
private function getClassFromFile($path)
Copy link
Member

Choose a reason for hiding this comment

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

I really think this is a bad idea and we should stick to what I described in #22397 (comment)
which doesn't require this magic logic.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, I was kind of at a loss on how to implement this otherwise... Any suggestions?

Copy link
Member

Choose a reason for hiding this comment

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

from this:

   App\Domain\*\CommandHandler\:
        resource: ../../src/Domain/*/CommandHandler
        tags: [command_handler]

we should parse App\Domain\*\CommandHandler\:

  • extract the first non variable part App\Domain\
  • load the classes with the existing logic but only the ones matching App\Domain\*\CommandHandler\ (which would have been turned into a regexp before of course, see existing logic in AddAnnotatedClassesToCachePass::patternsToRegexps().)

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for the direction - I will switch my implementation.

$parsingNamespace = true;
}

if (is_array($token) && $token[0] === T_CLASS) {
Copy link
Member

Choose a reason for hiding this comment

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

have you testing your code on a file containing anonymous classes ?

$class .= $token[1];
}

if ($token === ';') {
Copy link
Member

Choose a reason for hiding this comment

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

what about code using the bracketed notation for namespaces ?

throw new InvalidArgumentException(sprintf('Expected to find class "%s" in file "%s" while importing services from resource "%s", but it was not found! Check the namespace prefix used with the resource.', $class, $path, $pattern));
}

$r = $this->container->getReflectionClass($class);
Copy link
Member

Choose a reason for hiding this comment

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

I think this may still fail if the parent class is missing. Can you confirm @nicolas-grekas ?

Copy link
Member

Choose a reason for hiding this comment

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

not anymore
but anyway, this implementation is going to change completly (see my other comments)

@kbond
Copy link
Member Author

kbond commented Aug 25, 2017

I am switching the implementation away from the token matching...

That being said, I really like not requiring a namespace as the service id... Any thoughts on how we can remove the namespace requirement?

@nicolas-grekas
Copy link
Member

nicolas-grekas commented Aug 25, 2017

I really like not requiring a namespace as the service id

I know, you're not the only one, but that's just magic in the bad sense. That's exactly like calling composer to drop psr-0&4 and say: do get the classes yourself. Which is FRAGILE and will break anytime soon.
See the code you have to have. And think it's already broken by not taking if (...) {class foo{}} into account, or class_alias(), or etc.

@kbond
Copy link
Member Author

kbond commented Aug 25, 2017

Yeah, fair enough - I knew it was too good to be true 😄 - I was pretty excited for 5 minutes!

@kbond kbond changed the base branch from master to 3.4 August 25, 2017 18:25
@kbond kbond changed the base branch from 3.4 to master August 25, 2017 18:25
@nicolas-grekas nicolas-grekas added this to the 3.4 milestone Aug 28, 2017
@kbond
Copy link
Member Author

kbond commented Aug 28, 2017

Closing in favour of #23991.

@kbond kbond closed this Aug 28, 2017
@kbond kbond deleted the prototype-enhance branch August 28, 2017 13:15
nicolas-grekas added a commit that referenced this pull request Aug 29, 2017
… implementation) (kbond)

This PR was merged into the 3.4 branch.

Discussion
----------

[DI] Improve psr4-based service discovery (alternative implementation)

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

This is an alternative to #23986. It is simpler and doesn't require a second glob in the service id. This adds a `namespace` option. It is optional and if it isn't used, then it falls back to using the service id (current behaviour).

As stof mentions in #22397 (comment), it is consistent with the xml loader.

With this feature, you can define your services like this:

```yaml
services:
    command_handlers:
        namespace: App\Domain\
        resource: ../../src/Domain/*/CommandHandler
        tags: [command_handler]

    event_subscribers:
        namespace: App\Domain\
        resource: ../../src/Domain/*/EventSubscriber
        tags: [event_subscriber]
```

ping @stof, @nicolas-grekas

Commits
-------

00d7f6f [DI] improve psr4-based service discovery with namespace option
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.

4 participants