Skip to content

[DI][DX] Optional class for named services DX issue #21380

Closed
@ogizanagi

Description

@ogizanagi
Q A
Bug report? yesish
Feature request? no
BC Break report? not really
RFC? no
Symfony version 3.3

Since #21133, the class attribute isn't required anymore when using a classname as service id:

services:
    Vendor\Namespace\Class: ~

However, due to the current implementation, the following is considered valid too:

services:
    bar:
      arguments: ['foo']

The bar key is considered valid, and will be used as the Definition class, despite there is no bar class in the project.
Which means no compile-time exception. You'll only get:

Fatal error: Uncaught Symfony\Component\Debug\Exception\ClassNotFoundException: Attempted to load class "bar" from the global namespace.
Did you forget a "use" statement?

at runtime, when trying to use the service.
Previously, you got an error at compilation time:

Fatal error: Uncaught Symfony\Component\DependencyInjection\Exception\RuntimeException: The definition for "bar" has no class.

I think it's a DX regression, especially for someone not being aware of this behavior.

But the fact is that, looking at the tests, it seems expected.
In #20943 (comment), I suggested to enforce a leading backslash for global namespace classes, ie:

services:
    \bar: ~

but that's not something to consider, given one of the main benefits of declaring a service this way, is to call it using $container->get(\bar::class). Which doesn't resolves to a FQCN with a leading backslash.
So, unless we move the service id as definition class logic inside each loaders, it's probably a no-go...

First question: Should we care?

Then, what are the possible solutions ?

  1. Enforce a leading backslash from file loaders but keeping the ability to do
    $container->register(\ExistingClassFromTheGlobalNamespace::class)
    which means moving the logic to yaml and xml file loaders. Which creates an inconsistent behavior between formats and probably gives wrong responsibilities to the loaders compared to the compiler pass.
  2. Do not accept classes from the global namespace, or at least only accept classes from the global namespace starting with an uppercase char.
    In my experience, most services ids are lowercased (despite the fact case doesn't matter until [DI] Deprecate case insentivity of service identifiers #21193), whereas classnames are mainly capitalized (despite there is no recommendation about it in PSR-0/PSR-4 AFAIK), so it'll prevent WTF moments for a majority and looks sensible to me.
  3. Anything else?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions