Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony: How to get all services and their respective classes

What I'm trying to achieve is the following: Some of the services in my application carry a special annotation. Later, during the build process, a special command should find all files with that annotation.

My approach is to first load all bundles:

$container = $this->getContainer();

foreach ($container->getParameter('kernel.bundles') as $alias => $namespace)
    $bundle = $container->get('kernel')->getBundle($alias);

I’m stuck at this point. How do I get the $bundle instance to tell me its services?

Note: I'd also be happy with a solution that is not bundle-specific, i.e. one that loads all service definitions available. The ContainerBuilder has got a getDefinitions which looks promising, although I don’t know how to access it from a command.

I need to get a list with the service IDs and their classes – especially the classes, because those are the ones I need to load into the annotation reader.

Obviously, I don’t want to parse services.yml myself, and I’d also like to avoid loading an instance of each service from $container->getServiceIds().

(Btw, tagged services won’t help; I need annotations. And I want to detect annotated services automatically, because tagging them would require an additional step, which is unnecessary and error-prone.)

like image 786
lxg Avatar asked Oct 30 '15 19:10

lxg


1 Answers

A compiler pass will still do. But instead of finding tagged services you get all definitions. This has the advantages of working with the definitions, instead of instantiating every service.

Of course you need to create a manager class, which accepts holds all class names to use it later in your command.

<?php

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Reference;

class RegisterClassNamesPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        if (!$container->has('app.class_names_manager')) {
            return;
        }

        $manager = $container->findDefinition(
            'app.class_names_manager'
        );

        foreach ($container->getDefinitions() as $id => $definition) {
            $class = $container->getParameterBag()->resolveValue($def->getClass());

            $definition->addMethodCall(
                'addClassName',
                array($id, $class)
            );
        }
    }
}
like image 185
Emii Khaos Avatar answered Sep 27 '22 00:09

Emii Khaos