4

I'm sorry to say I can't find a way to add a default value to a "symfony/config": "2.6.4" ConfigurationInterface !

What's wanted is this type of config :

X:
    Y:
        - test
        - testing

With default to :

X:
    Y:
        - test

By "default" I mean : if Y config branch is not set on the read configuration file, the $processor->processConfiguration should add it (and it does ! If I remove the ->prototype...)

Here is my code :

class Definition implements ConfigurationInterface
{
    /**
     * {@inheritdoc}
     */
    public function getConfigTreeBuilder()
    {
        $treeBuilder = new TreeBuilder();
        $rootNode = $treeBuilder->root("X");
        $rootNode
            ->children()
                ->arrayNode("Y")
                    ->addDefaultsIfNotSet()
                    ->info("Multiple values can be used")
                    ->cannotBeEmpty()
                    ->addDefaultIfNotSet()
                    ->defaultValue(array("test"))
                    ->prototype("scalar")
                        ->validate()
                        ->ifNotInArray(array("test", "testing"))
                            ->thenInvalid("Invalid value %s")
                        ->end()
                    ->end()
                ->end()
            ->end()
        ;

        return $treeBuilder;
    }
}

Sure, I read this question Using the Symfony2 configuration class, how do I define an array node whose children don't have keys?

My current code implements this way as you can read, but it does not work, my code throws :

[Symfony\Component\Config\Definition\Exception\InvalidDefinitionException]
  ->addDefaultsIfNotSet() is not applicable to prototype nodes at path "X.Y"

3 Answers 3

2

For reference, I finally got it via a variableNode, just a minute before hitting the wall with my head ;)

class Definition implements ConfigurationInterface
{
    /**
     * {@inheritdoc}
     */
    public function getConfigTreeBuilder()
    {
        $treeBuilder = new TreeBuilder();
        $rootNode = $treeBuilder->root("X");
        $rootNode
            ->children()
                ->variableNode("Y")
                    ->info("Multiple values can be used")
                    ->cannotBeEmpty()
                    ->defaultValue(array("test"))
                    ->validate()
                        ->always(function ($values) {
                            foreach ((array) $values as $value) {
                                if (! in_array($value, array("test", "testing"))) {
                                    throw new \Symfony\Component\Config\Definition\Exception\InvalidTypeException("Invalid value ".$value);
                                }
                            }
                            return (array) $values;
                        })
                    ->end()
                ->end()
            ->end()
        ;

        return $treeBuilder;
    }
}

It seems there is no way to do this with an arrayNode ! But if one find how, please do not hesitate to answer, I'll be pleased to accept the answer using arrayNode, as integrated validation is probably better than mine...

Sign up to request clarification or add additional context in comments.

Comments

1

What about:

<?php
    $rootNode
        ->children()
            ->arrayNode("Y")
                ->defaultValue(array("test"))
                ->prototype("scalar")
                    ->validate()
                    ->ifNotInArray(array("test", "testing"))
                        ->thenInvalid("Invalid value %s")
                    ->end()
                ->end()
            ->end()
        ->end()
    ;

Another question is, why not restructuring the config. You want a list of test or test, testing or testing. Why don't you configure it like:

X:
  Y:
    test: true
    testing: false

With X.Y.test = true by default and X.Y.testing = false? Then your Configuration would be very easy.

Comments

0

You can do it like so:

$node
    ->fixXmlConfig('driver')
    ->children()
        ->arrayNode('drivers')
            ->scalarPrototype()->end()
        ->end()
    ->end()
;

This allows:

drivers: ['mysql', 'sqlite']

More info here https://symfony.com/doc/current/components/config/definition.html#array-node-options

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.