phpxmlsymfonyconfigurationsymfony-2.1

Define Symfony 2 tag attribute as an array in XML configuration?


<service id="my_service">
    <tag name="my_transport" supports="feature1, feature2, feature3" />
</service>

Would be possible to define supports attribute as array when dealing with XML configuration, instead of doing a preg_split?


Solution

  • There is no way do define attribute as array.

    DependencyInjection loaders don't support this. (Ex. loading from yml throws exception A "tags" attribute must be of a scalar-type (...) if you try this)

    XmlFileLoader loading tags uses phpize parse attribute value as null, boolean, numeric or string.

    Adding tag to service definition doesn't override previous added tag's definition, but adds new entry to array.

    public function addTag($name, array $attributes = array())
    {
        $this->tags[$name][] = $attributes;
    
        return $this;
    }
    

    So you should try create multiple <tag> elements (like Wouter J said)

    If your XML file will be like

    <service id="my_service">
        <tag name="my_transport" supports="feature1" />
        <tag name="my_transport" supports="feature2" />
        <tag name="my_transport" supports="feature3" />
    </service>
    

    then $attributes for tag my_transport will be

    Array
    (
        [0] => Array
            (
                [supports] => feature1
            )
    
        [1] => Array
            (
                [supports] => feature2
            )
    
        [2] => Array
            (
                [supports] => feature3
            )
    
    )
    

    And sample usage

    use Symfony\Component\DependencyInjection\Reference;
    use Symfony\Component\DependencyInjection\ContainerBuilder;
    use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
    
    class MyCompilerPass implements CompilerPassInterface
    {
        public function process(ContainerBuilder $container)
        {
            $definition = $container->getDefinition('my_transport_service');
    
            // Extensions must always be registered before everything else.
            // For instance, global variable definitions must be registered
            // afterward. If not, the globals from the extensions will never
            // be registered.
            $calls = $definition->getMethodCalls();
            $definition->setMethodCalls(array());
            foreach ($container->findTaggedServiceIds('my_transport') as $id => $attributes) {
                // print_r($attributes);
                foreach($attributes as $attrs)
                {
                    switch($attrs['supports']){
                      case 'feature1':
                          $definition->addMethodCall('addTransportFeature1', array(new Reference($id)));
                          break;
                      case 'feature2':
                          $definition->addMethodCall('addTransportFeature2', array(new Reference($id)));
                          break;
                      case 'feature3':
                          $definition->addMethodCall('addTransportFeature3', array(new Reference($id)));
                          break;
                    }
                }
            }
            $definition->setMethodCalls(array_merge($definition->getMethodCalls(), $calls));
        }
    }