<p dir="auto">Currently, the only way to make an <code class="notranslate">arrayNode</code> a map, rather than a list, is to use <code class="notranslate">useAttributeAsKey</code>, the problem with that method is that it requires you to use an attribute within the array as the key. What if you want to use the array key as the .. array key?</p>
<p dir="auto">For example</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="            -&gt;arrayNode('servers')
                -&gt;prototype('array')
                    -&gt;children()
                        -&gt;scalarNode('username')
                            -&gt;isRequired()
                        -&gt;end()
                        -&gt;scalarNode('password')
                            -&gt;isRequired()
                        -&gt;end()
                    -&gt;end()
                -&gt;end()
            -&gt;end()"><pre class="notranslate"><code class="notranslate">            -&gt;arrayNode('servers')
                -&gt;prototype('array')
                    -&gt;children()
                        -&gt;scalarNode('username')
                            -&gt;isRequired()
                        -&gt;end()
                        -&gt;scalarNode('password')
                            -&gt;isRequired()
                        -&gt;end()
                    -&gt;end()
                -&gt;end()
            -&gt;end()
</code></pre></div>
<p dir="auto">with config</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="something:
    servers:
        serverA:
            username: userA
            password: passwordA
        serverB:
            username: userB
            password: passwordB"><pre class="notranslate"><code class="notranslate">something:
    servers:
        serverA:
            username: userA
            password: passwordA
        serverB:
            username: userB
            password: passwordB
</code></pre></div>
<p dir="auto">comes out as</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="servers [
    serverA =&gt; [username: userA, password: passwordA],
    serverB =&gt; [username: userB, password: passwordB],
]"><pre class="notranslate"><code class="notranslate">servers [
    serverA =&gt; [username: userA, password: passwordA],
    serverB =&gt; [username: userB, password: passwordB],
]
</code></pre></div>
<p dir="auto">Great! Until.. you merge config across files. If you put serverA in a file and import it, then add serverB, it comes out like -</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="servers [
    serverA =&gt; [username: userA, password: passwordA],
    0 =&gt; [username: userB, password: passwordB],
]"><pre class="notranslate"><code class="notranslate">servers [
    serverA =&gt; [username: userA, password: passwordA],
    0 =&gt; [username: userB, password: passwordB],
]
</code></pre></div>
<p dir="auto">The key for the nodes get lost.  This issue is described on <a href="https://symfony.com/doc/current/components/config/definition.html" rel="nofollow">https://symfony.com/doc/current/components/config/definition.html</a></p>
<blockquote>
<p dir="auto">As of writing this, there is an inconsistency: if only one file provides the configuration in question, the keys (i.e. sf_connection and default) are not lost. But if more than one file provides the configuration, the keys are lost as described above.</p>
</blockquote>
<p dir="auto">that's ..not great. Especially if you're relying on referencing that key from somewhere else in your config (i.e. <code class="notranslate">default_server: ..</code>). However, since we've not indicated the <code class="notranslate">arrayNode</code> is a map, I guess this behaviour was undefined (probably odd it kept the string keys in the first place).</p>
<p dir="auto">You could argue that if the key is important, to put it in the attributes, like</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="something:
    servers:
        -
            username: userA
            password: passwordA
            server: serverA
        -
            username: userB
            password: passwordB
            server: serverB"><pre class="notranslate"><code class="notranslate">something:
    servers:
        -
            username: userA
            password: passwordA
            server: serverA
        -
            username: userB
            password: passwordB
            server: serverB
</code></pre></div>
<p dir="auto">with <code class="notranslate">useAttributeAsKey('server')</code>. However, this is not a very efficient way of writing configuration - it's clearly more for XML based processing, not YAML.</p>
<p dir="auto">One way people have been getting around this is to use <code class="notranslate">useAttributeAsKey</code> with an attribute that doesn't exist, like <code class="notranslate">-&gt;useAttributeAsKey('some_field_that_doesnt_exist')</code> which seems pretty hacky.</p>
<p dir="auto">Suggest something like</p>
<ol dir="auto">
<li>
<p dir="auto">adding <code class="notranslate">-&gt;useAsMap()</code> which turns the array into a map internally, or</p>
</li>
<li>
<p dir="auto">breaking <code class="notranslate">arrayNode</code> into <code class="notranslate">listNode</code> and <code class="notranslate">mapNode</code> types (with <code class="notranslate">arrayNode</code> defaulting to <code class="notranslate">listNode</code> for backward compatibility for a while).</p>
</li>
</ol>
<p dir="auto">Related</p>
<ul dir="auto">
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="46645800" data-permission-text="Title is private" data-url="https://github.com/symfony/symfony/issues/12304" data-hovercard-type="issue" data-hovercard-url="/symfony/symfony/issues/12304/hovercard" href="https://github.com/symfony/symfony/issues/12304">#12304</a></li>
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="49694708" data-permission-text="Title is private" data-url="https://github.com/symfony/symfony-docs/issues/4509" data-hovercard-type="issue" data-hovercard-url="/symfony/symfony-docs/issues/4509/hovercard" href="https://github.com/symfony/symfony-docs/issues/4509">symfony/symfony-docs#4509</a></li>
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="127408578" data-permission-text="Title is private" data-url="https://github.com/symfony/symfony/issues/17436" data-hovercard-type="issue" data-hovercard-url="/symfony/symfony/issues/17436/hovercard" href="https://github.com/symfony/symfony/issues/17436">#17436</a></li>
<li><a href="https://stackoverflow.com/questions/10924504/allowing-key-value-pairs-in-symfony-2-bundle-semantic-configuration" rel="nofollow">https://stackoverflow.com/questions/10924504/allowing-key-value-pairs-in-symfony-2-bundle-semantic-configuration</a></li>
</ul>
<p dir="auto">When passing to 'useAttributeAsKey' function key that is not used in below config, in the test environment the side effect is that $config in [Bundle]Extension.php contains settings only for this env. When this method is not being used at all, the $config contains config for each env.</p>
<p dir="auto"><strong>Bundle\DependencyInjection\Configuration::getConfigTreeBuilder():</strong></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="$root-&gt;children()
            -&gt;arrayNode('some_config')
                -&gt;prototype('array')
                    -&gt;children()
                        -&gt;scalarNode('some_key')-&gt;end()
                    -&gt;end()
                -&gt;end()
            -&gt;end()
        -&gt;end();"><pre class="notranslate"><code class="notranslate">$root-&gt;children()
            -&gt;arrayNode('some_config')
                -&gt;prototype('array')
                    -&gt;children()
                        -&gt;scalarNode('some_key')-&gt;end()
                    -&gt;end()
                -&gt;end()
            -&gt;end()
        -&gt;end();
</code></pre></div>
<p dir="auto"><strong>config_dev:</strong></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="
my_app:
    some_config:
        Option1:
            some_key: yyyy
        Option2:
            some_key: xxx"><pre class="notranslate"><code class="notranslate">
my_app:
    some_config:
        Option1:
            some_key: yyyy
        Option2:
            some_key: xxx
</code></pre></div>
<p dir="auto"><strong>config_test:</strong></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="
my_app:
    some_config:
        Option1:
            some_key: aaaaa
        Option2:
            some_key: bbbbb"><pre class="notranslate"><code class="notranslate">
my_app:
    some_config:
        Option1:
            some_key: aaaaa
        Option2:
            some_key: bbbbb
</code></pre></div>
<p dir="auto"><strong>Bundle\DependencyInjection\BundleExtension::load():</strong></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="....

var_dump($config['some_config'])
...."><pre class="notranslate"><code class="notranslate">....

var_dump($config['some_config'])
....
</code></pre></div>
<h2 dir="auto">Expected result on test env:</h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="array (size=2)
        Option1 =&gt;
            some_key: aaaaa
        Option2 =&gt;
            some_key: bbbbb
"><pre class="notranslate"><code class="notranslate">array (size=2)
        Option1 =&gt;
            some_key: aaaaa
        Option2 =&gt;
            some_key: bbbbb

</code></pre></div>
<h2 dir="auto">Actual result:</h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="array (size=4)
        Option1 =&gt;
            some_key: yyyy
        Option2 =&gt;
            some_key: xxx
        0 =&gt;
            some_key: aaaaa
        1 =&gt;
            some_key: bbbbb"><pre class="notranslate"><code class="notranslate">array (size=4)
        Option1 =&gt;
            some_key: yyyy
        Option2 =&gt;
            some_key: xxx
        0 =&gt;
            some_key: aaaaa
        1 =&gt;
            some_key: bbbbb
</code></pre></div>
<h2 dir="auto">How to fix that?</h2>
<p dir="auto"><strong>Bundle\DependencyInjection\Configuration::getConfigTreeBuilder():</strong></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="$root-&gt;children()
            -&gt;arrayNode('some_config')
            -&gt;useAttributeAsKey('some_not_existing_key_to_prevent_associative_array_in_different_env_SYMFONY_BUG')
                -&gt;prototype('array')
                    -&gt;children()
                        -&gt;scalarNode('some_key')-&gt;end()
                    -&gt;end()
                -&gt;end()
            -&gt;end()
        -&gt;end();"><pre class="notranslate"><code class="notranslate">$root-&gt;children()
            -&gt;arrayNode('some_config')
            -&gt;useAttributeAsKey('some_not_existing_key_to_prevent_associative_array_in_different_env_SYMFONY_BUG')
                -&gt;prototype('array')
                    -&gt;children()
                        -&gt;scalarNode('some_key')-&gt;end()
                    -&gt;end()
                -&gt;end()
            -&gt;end()
        -&gt;end();
</code></pre></div>
<p dir="auto">Then:</p>
<p dir="auto"><strong>Bundle\DependencyInjection\BundleExtension::load():</strong></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="....
var_dump($config['some_config'])
...."><pre class="notranslate"><code class="notranslate">....
var_dump($config['some_config'])
....
</code></pre></div>
<h2 dir="auto">Actual result on test env after fixing:</h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="array (size=2)
        Option1 =&gt;
            some_key: aaaaa
        Option2 =&gt;
            some_key: bbbbb"><pre class="notranslate"><code class="notranslate">array (size=2)
        Option1 =&gt;
            some_key: aaaaa
        Option2 =&gt;
            some_key: bbbbb
</code></pre></div>
<p dir="auto">But I don't think it's a proper behaviour.</p>