Note: I'm migrating from gonzalo123.com to here. When I finish I'll swap the DNS to here. The "official" blog will be always gonzalo123.com

      Building a Pimple/Container from a YAML file

      The last May I attended to the great deSymfony day conference in Barcelona. At speaker’s dinner I had a great conversation with Máximo Cuadros about Dependency Injection Containers. We discuss about the customisation of containers. I said that I prefer Symfony´s DIC instead of Pimple, mainly because its configuration with YAML (or even xml) files. But In fact we can customise Pimple/Containers with YAML files in a similar way than we do it with Symfony’s DIC. In this example we’re going to see one way to do it.

      We can easily extend the Pimple/Container and add a function to load a YAML files, parse them and build the container. But doing this we’re violating various SOLID principles. First we’re violating the Open-Close principle, because to extend our Pimple/Container with the new functionality we are adding new code within an existing class. We’re also violating the Dependency Inversion Principle and our new Pimple/Container is going to be harder to maintain. And finally we’re obviously violating the Single Responsibility Principle, because our new Pimple/Container is not only a DIC, it’s also a YAML parser.

      There’s another way to perform this operation without upsetting SOLID principles. We can use the Symfony’s Config component

      The idea is simple. Imagine this simple application:

      use Pimple\Container;
       
      $container = new Container();
      $container['name'] = 'Gonzalo';
       
      $container['Curl'] = function () {
          return new Curl();
      };
      $container['Proxy'] = function ($c) {
          return new Proxy($c['Curl']);
      };
       
      $container['App'] = function ($c) {
          return new App($c['Proxy'], $c['name']);
      };
       
      $app = $container['App'];
      echo $app->hello();
      

      We define the dependencies with code. But we want to define dependencies using a yml file for example:

      parameters:
        name: Gonzalo
       
      services:
        App:
          class:     App
          arguments: [@Proxy, %name%]
        Proxy:
          class:     Proxy
          arguments: [@Curl]
        Curl:
          class:     Curl
      

      As we can see we’re using a similar syntax than Symfony’s DIC YAML files. Now, with our new library we can use the following code:

      use Pimple\Container;
      use G\Yaml2Pimple\ContainerBuilder;
      use G\Yaml2Pimple\YamlFileLoader;
      use Symfony\Component\Config\FileLocator;
       
      $container = new Container();
       
      $builder = new ContainerBuilder($container);
      $locator = new FileLocator(__DIR__);
      $loader = new YamlFileLoader($builder, $locator);
      $loader->load('services.yml');
       
      $app = $container['App'];
      echo $app->hello();
      

      Now our Pimple/Container is just a Pimple/Container nothing more. It doesn’t know anything about yaml, parsers and thing like that. It’s doesn’t have any extra responsibility. The responsibility of the parser falls on YamlFileLoader You can see the library in my github account. It’s but one usage example of Symfony’s Config component. It only allows Yaml files, but it can be extended with Xml files adding a XmlFileLoader.

      comments powered by Disqus