Search code examples
symfonyconfigurationautocompletephpstormtype-hinting

How to get autocompletion for container using phpstorm and symfony2 plugin?


I use phpstorm. When developing a symfony2 application I am used to the symfony2 plugin providing an autocompletion for container services:

[symfony2 example

This offers completion on the returned objects as well.

Is there a way to get the service completion to work when using the container component in a non-symfony PHP project that uses only parts of the symfony2 components, i.e. the container component?

I know that in phpstorm's settings:

Other Settings > Symfony2 Plugins > Container

I could add additonal xml container files, yet I have no clue what it should look like.

How would I create such a file?

For instance, I create a container by:

/**
 * @return ContainerBuilder
 * @todo Initialize the container on a more reasonable place
 */
private function createServiceContainer()
{
    $container = new ContainerBuilder();
    $loader = new YamlFileLoader($container, new FileLocator(ROOT_PATH . '/config'));
    $loader->load('services.yml');

    return $container;
}

And my services.yml looks like this:

services:
    redis:
        class: App\Framework\RedisService
    doctrine:
        class: DoctrineService
        factory: [\App\Database\DoctrineService, getDoctrine]

How could I create a container.xml that would be understood by the symfony2 plugin and offer me the two services redis and doctrine in the container?


Solution

  • I have created an command:

    <?php
    namespace App\Command;
    
    use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ContainerBuilderDebugDumpPass;
    use Symfony\Component\Config\FileLocator;
    use Symfony\Component\Console\Command\Command;
    use Symfony\Component\Console\Input\InputInterface;
    use Symfony\Component\Console\Output\OutputInterface;
    use Symfony\Component\DependencyInjection\ContainerBuilder;
    use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
    
    /**
     * ContainerRefreshCommand
     **/
    class ContainerRefreshCommand extends Command
    {
        /**
         * Configures the current command.
         */
        protected function configure()
        {
            $this
                ->setName('container:refresh')
                ->setDescription('refreshes the container file for usage with phpstorm');
        }
    
    
        /**
         * @param InputInterface  $input
         * @param OutputInterface $output
         */
        protected function execute(InputInterface $input, OutputInterface $output)
        {
            $container = new ContainerBuilder();
    
    
            $loader = new YamlFileLoader($container, new FileLocator(ROOT_PATH . '/config'));
            $loader->load('services.yml');
    
            $container->setParameter('debug.container.dump', ROOT_PATH . '/dev/appDevDebugProjectContainer.xml');
            $containerFile = new ContainerBuilderDebugDumpPass();
    
            $containerFile->process($container);
        }
    }
    

    I have then added the file from my project root:

    ./dev/appDevDebugProjectContainer.xml
    

    in the container definition.

    I then had to change the class name of the doctrine service. It appears to be anything goes there, yet this string is what the symfony2 plugins uses to detect the service.

    I then got auto-completion for container services.

    One has to note that the class property in services.yml is important as well. Since the object I actually get by container->get('doctrine'), is an instance of an EntityManager I have to define this way to get autocompletion:

    doctrine:
        class: Doctrine\ORM\EntityManager
        factory: [\App\Database\DoctrineService, getDoctrine]