How to access nested parameter values in Symfony2? How to access nested parameter values in Symfony2? symfony symfony

How to access nested parameter values in Symfony2?


In all the symfony config files I've seen, the entries under 'parameters:' have always been fully qualified. I don't fully understand why this is but it may help you to write the entries in your parameters.yml like this:

category1.var1: xxxcategory1.var2: yyycategory1.var3. zzzcategory2.subcategory1.var1: 5category2.subcategory1.var2: 10category2.subcategory2.var1: foocategory2.subcategory2.var2: bar

... and so on.

EDIT

I tried pasting the nested parameter from the question into parameters.local.yml in one of my projects and ran a trivial unit test to retrieve that and a fully qualified parameter from the container e.g.

$testUserEmail = $container->getParameter('test.user.email');$this->assertEquals('dahlia.flower@randomtest.com', $testUserEmail);$testParam = $container->getParameter('category.var');$this->assertEquals('test', $testParam);

The fully qualified parameter was fine, attempting to get the nested parameter resulted in an InvalidArgumentException: The parameter category.var must be defined. I don't think parameters can be defined with nesting.


$this->container->getParameter('category')['var']

I have tested that on symfony 2.8 and it worked for me.


Or you can write simple ParameterBag which can implement nested parameters dynamically (without config values duplicity):

<?phpnamespace Your\Namespace;use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;class ParameterBagNested extends ParameterBag{    /**     * wire $this->set() logic into add() too     *     * @param array $parameters     */    public function add( array $parameters )    {        foreach ( $parameters as $name => $value ) {            $this->set( $name, $value );        }    }    /**     * sets all levels of nested array parameters with dot notation     * - loggly[host: loggly.com] will be translated this way:     *  - loggly: [host: loggly.com] - standard array parameter will be left as is     *  - loggly.host: loggly.com - nested variables ar translated so you can access them directly too as parent.variable     *     * @param string $name     * @param mixed $value     */    public function set( $name, $value )    {        if ( $this->has( $name ) ) {            // this is required because of array values            // we can have arrays defined there, so we need to remove them first            // otherwise some subvalues would to remain in the system and as a result, arrays would be merged, not overwriten by set()            $this->remove( $name );        }        $this->setNested( $name, $value );    }    /**     * remove checks even if name is not array     *     * @param string $name     */    public function remove( $name )    {        $value = $this->get( $name );        if ( is_array( $value ) ) {            foreach ( $value as $k => $v ) {                $this->remove( $name . '.' . $k, $v );            }        }        if ( strpos( $name, '.' ) !== FALSE ) {            $parts = explode( '.', $name );            $nameTopLevel = reset( $parts );            array_shift( $parts );            $topLevelData = $this->removeKeyByAddress( $this->get( $nameTopLevel ), $parts );            ksort( $topLevelData );            $this->setNested( $nameTopLevel, $topLevelData );        }        parent::remove( $name );    }    /**     * @param array $data     * @param array $addressParts     *     * @return array     */    private function removeKeyByAddress( $data, $addressParts )    {        $updatedLevel = & $data;        $i = 1;        foreach ( $addressParts as $part ) {            if ( $i === count( $addressParts ) ) {                unset( $updatedLevel[$part] );            } else {                $updatedLevel = & $updatedLevel[$part];                $i++;            }        }        return $data;    }    /**     * @see set()     *     * @param string $name     * @param mixed $value     */    private function setNested( $name, $value )    {        if ( is_array( $value ) ) {            foreach ( $value as $k => $v ) {                $this->setNested( $name . '.' . $k, $v );            }        }        parent::set( $name, $value );    }}

phpunit Test:

<?phpnamespace Your\Namespace;use Symfony\Component\DependencyInjection\Tests\ParameterBag\ParameterBagTest;/** * its essential to use ParameterBagNested as ParameterBag because this way we run even parent class tests upon it * parent class is part of Symfony DIC standard test suite and we use it here just for check if our parameter bag is still ok */use SBKS\DependencyInjection\ParameterBag\ParameterBagNested as ParameterBag;/** * testing basic and even added ParameterBag functionality */class ParameterBagNestedTest extends ParameterBagTest{    public function testConstructorNested()    {        $bag = new ParameterBag(            array(                'foo' => array( 'foo1' => 'foo' ),                'bar' => 'bar',            )        );        $this->assertEquals(             array(                 'foo.foo1' => 'foo',                 'foo' => array(                     'foo1' => 'foo',                 ),                 'bar' => 'bar',             ),             $bag->all(),             '__construct() takes an array of parameters as its first argument'        );    }    public function testRemoveNested()    {        $bag = new ParameterBag(            array(                'foo' => array(                    'foo1' => array(                        'foo11' => 'foo',                        'foo12' => 'foo',                    ),                    'foo2' => 'foo',                ),                'bar' => 'bar',            )        );        $bag->remove( 'foo.foo1.foo11' );        $this->assertEquals(             array(                 'foo' => array(                     'foo1' => array(                         'foo12' => 'foo',                     ),                     'foo2' => 'foo',                 ),                 'foo.foo1' => array( 'foo12' => 'foo' ),                 'foo.foo1.foo12' => 'foo',                 'foo.foo2' => 'foo',                 'bar' => 'bar',             ),             $bag->all(),             '->remove() removes a parameter'        );        $bag->remove( 'foo' );        $this->assertEquals(             array(                 'bar' => 'bar',             ),             $bag->all(),             '->remove() removes a parameter'        );    }    public function testSetNested()    {        $bag = new ParameterBag(            array(                'foo' => array(                    'foo1' => array(                        'foo11' => 'foo',                        'foo12' => 'foo',                    ),                    'foo2' => 'foo',                ),            )        );        $bag->set( 'foo', 'foo' );        $this->assertEquals( array( 'foo' => 'foo' ), $bag->all(), '->set() sets the value of a new parameter' );    }    public function testHasNested()    {        $bag = new ParameterBag(            array(                'foo' => array(                    'foo1' => array(                        'foo11' => 'foo',                        'foo12' => 'foo',                    ),                    'foo2' => 'foo',                ),            )        );        $this->assertTrue( $bag->has( 'foo' ), '->has() returns true if a parameter is defined' );        $this->assertTrue( $bag->has( 'foo.foo1' ), '->has() returns true if a parameter is defined' );        $this->assertTrue( $bag->has( 'foo.foo1.foo12' ), '->has() returns true if a parameter is defined' );        $this->assertTrue( $bag->has( 'foo.foo2' ), '->has() returns true if a parameter is defined' );    }}

Then you can use it by injecting Parameter bag into ContainerBuilder:

$parameterBag = new \Your\Namespace\ParameterBagNested();$container = new ContainerBuilder($parameterBag);

Thats all, you can use nested parameter with dot notation now in Symfony DI container.

If you are using Symfony plugin in phpstorm it will autocomplete your nested attributes with dot notation too.