8000 Fixing a bug where abstract classes were wired with the prototype loader by weaverryan · Pull Request #22681 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

Fixing a bug where abstract classes were wired with the prototype loader #22681

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
May 11, 2017

Conversation

weaverryan
Copy link
Member
Q A
Branch? master
Bug fix? yes
New feature? no
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets none
License MIT
Doc PR n/a

The prototype/PSR-4 loader currently tries to wire abstract classes. The problem is if, for example, you have, for example:

abstract class BaseCommand extends Command
{
}

If this is registered as a service, and you have autoconfigure, then the console Application will try to use this a command.

Was there some reason abstract classes were originally allowed to be registered as services with the PSR4/prototype loader? I don't know if there is a real use-case for registering abstract classes. If you wanted to use that service as a parent service... then you'll probably be configuring it yourself anyways. We could also fix this by changing all tags compiler passes to skip classes that are abstract... if there is a use-case for Abstract classes being auto-registered.

Cheers!

@@ -108,7 +108,7 @@ private function findClasses($namespace, $pattern)
if (!$r = $this->container->getReflectionClass($class)) {
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));
}
if (!$r->isInterface() && !$r->isTrait()) {
if (!$r->isInterface() && !$r->isTrait() && !$r->isAbstract()) {
Copy link
Member

Choose a reason for hiding this comment

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

$r->isInstantiable?

Copy link
Member Author

Choose a reason for hiding this comment

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

Nice idea 👍

@weaverryan weaverryan force-pushed the no-prototype-abstract-class branch from cd38948 to ae3ebc2 Compare May 10, 2017 13:29
@@ -108,7 +108,8 @@ private function findClasses($namespace, $pattern)
if (!$r = $this->container->getReflectionClass($class)) {
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));
}
if (!$r->isInterface() && !$r->isTrait()) {
// skip interfaces, traits, abstract classes & private constructors
if ($r->isInstantiable()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not certain we should skip private constructors, users could define a factory when having some.

@weaverryan weaverryan force-pushed the no-prototype-abstract-class branch from ae3ebc2 to 5326bab Compare May 11, 2017 09:43
@weaverryan
Copy link
Member Author

I just changed away from ->isInstantiable() to allow for private constructors. Interfaces, traits and abstract classes can never be instantiated - it would never make sense for those to be services on their own. However, a class with a private constructor is still a class that could be instantiated. In theory, I could load a directory full of these, then use _instanceof to configure all of them to use a factory. Qualitatively, they're different than interfaces, traits, abstract classes. I think this way is the "proper", not-too-clever solution.

@fabpot
Copy link
Member
fabpot commented May 11, 2017

Thank you @weaverryan.

@fabpot fabpot merged commit 5326bab into symfony:master May 11, 2017
fabpot added a commit that referenced this pull request May 11, 2017
…ototype loader (weaverryan)

This PR was merged into the 3.3-dev branch.

Discussion
----------

Fixing a bug where abstract classes were wired with the prototype loader

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | none
| License       | MIT
| Doc PR        | n/a

The prototype/PSR-4 loader currently tries to wire abstract classes. The problem is if, for example, you have, for example:

```php
abstract class BaseCommand extends Command
{
}
```

If this is registered as a service, and you have `autoconfigure`, then the console `Application` will try to use this a command.

Was there some reason abstract classes were originally allowed to be registered as services with the PSR4/prototype loader? I don't know if there is a real use-case for registering abstract classes. If you wanted to use that service as a parent service... then you'll probably be configuring it yourself anyways. We could also fix this by changing all tags compiler passes to skip classes that are abstract... *if* there is a use-case for Abstract classes being auto-registered.

Cheers!

Commits
-------

5326bab Fixing a bug where abstract classes were wired
@weaverryan weaverryan deleted the no-prototype-abstract-class branch May 12, 2017 14:14
@fabpot fabpot mentioned this pull request May 17, 2017
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
0