<table role="table">
<thead>
<tr>
<th>Q</th>
<th>A</th>
</tr>
</thead>
<tbody>
<tr>
<td>Bug report?</td>
<td>yes</td>
</tr>
<tr>
<td>Feature request?</td>
<td>no</td>
</tr>
<tr>
<td>BC Break report?</td>
<td>no</td>
</tr>
<tr>
<td>RFC?</td>
<td>no</td>
</tr>
<tr>
<td>Symfony version</td>
<td>3.2.7</td>
</tr>
</tbody>
</table>
<p dir="auto">If you have a configuration node with a non-string type, e.g. <code class="notranslate">IntegerNode</code>, and pass an env variable, even though the env variable will be resolved in an integer, the value won't pass the validation and throw an error when booting.</p>
<p dir="auto">e.g.:</p>
<div class="highlight highlight-source-yaml notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="parameters:
    int_val_param: '%env(INT_ENV_VAL)%'

app:
    int_val: '%int_val_param%'"><pre class="notranslate"><span class="pl-ent">parameters</span>:
    <span class="pl-ent">int_val_param</span>: <span class="pl-s"><span class="pl-pds">'</span>%env(INT_ENV_VAL)%<span class="pl-pds">'</span></span>

<span class="pl-ent">app</span>:
    <span class="pl-ent">int_val</span>: <span class="pl-s"><span class="pl-pds">'</span>%int_val_param%<span class="pl-pds">'</span></span></pre></div>
<p dir="auto">or:</p>
<div class="highlight highlight-source-yaml notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="app:
    int_val: '%env(INT_ENV_VAL)%'"><pre class="notranslate"><span class="pl-ent">app</span>:
    <span class="pl-ent">int_val</span>: <span class="pl-s"><span class="pl-pds">'</span>%env(INT_ENV_VAL)%<span class="pl-pds">'</span></span></pre></div>
<p dir="auto">with:</p>
<div class="highlight highlight-text-html-php notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// Configuration file

public function getConfigTreeBuilder()
{
    $treeBuilder = new TreeBuilder();

    $treeBuilder-&gt;root('app')
        -&gt;children()
            -&gt;integerNode('int_val')
            -&gt;isRequired()
            -&gt;end()
        -&gt;end()
    ;

    return $treeBuilder;
}"><pre class="notranslate"><span class="pl-c">// Configuration file</span>

<span class="pl-k">public</span> <span class="pl-k">function</span> <span class="pl-en">getConfigTreeBuilder</span>()
{
    <span class="pl-s1"><span class="pl-c1">$</span>treeBuilder</span> = <span class="pl-k">new</span> <span class="pl-v">TreeBuilder</span>();

    <span class="pl-s1"><span class="pl-c1">$</span>treeBuilder</span>-&gt;<span class="pl-en">root</span>(<span class="pl-s">'app'</span>)
        -&gt;<span class="pl-en">children</span>()
            -&gt;<span class="pl-en">integerNode</span>(<span class="pl-s">'int_val'</span>)
            -&gt;<span class="pl-en">isRequired</span>()
            -&gt;<span class="pl-en">end</span>()
        -&gt;<span class="pl-en">end</span>()
    ;

    <span class="pl-k">return</span> <span class="pl-s1"><span class="pl-c1">$</span>treeBuilder</span>;
}</pre></div>
<p dir="auto">will throw:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="  [Symfony\Component\DependencyInjection\Exception\EnvParameterException]
  Incompatible use of dynamic environment variables &quot;INT_ENV_VAL&quot; found in parameters.

  [Symfony\Component\Config\Definition\Exception\InvalidTypeException]
  Invalid type for path &quot;app.int_val&quot;. Expected int, but got 'string'."><pre class="notranslate"><code class="notranslate">  [Symfony\Component\DependencyInjection\Exception\EnvParameterException]
  Incompatible use of dynamic environment variables "INT_ENV_VAL" found in parameters.

  [Symfony\Component\Config\Definition\Exception\InvalidTypeException]
  Invalid type for path "app.int_val". Expected int, but got 'string'.
</code></pre></div>
<p dir="auto">Issue reproduced on the repo: <a href="https://github.com/theofidry/symfony-22594">https://github.com/theofidry/symfony-22594</a></p>
<p dir="auto">Depends on: <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="4066627" data-permission-text="Title is private" data-url="https://github.com/symfony/symfony/issues/3879" data-hovercard-type="issue" data-hovercard-url="/symfony/symfony/issues/3879/hovercard" href="https://github.com/symfony/symfony/issues/3879">#3879</a>, <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="4158065" data-permission-text="Title is private" data-url="https://github.com/symfony/symfony/issues/3968" data-hovercard-type="pull_request" data-hovercard-url="/symfony/symfony/pull/3968/hovercard" href="https://github.com/symfony/symfony/pull/3968">#3968</a> (<code class="notranslate">OptionsParser::replaceDefaults</code> is required)</p>
<p dir="auto">I want to add three options to the ChoiceType that abstract functionality of EntityType for use in all choice fields. See also <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="3451976" data-permission-text="Title is private" data-url="https://github.com/symfony/symfony/issues/3479" data-hovercard-type="pull_request" data-hovercard-url="/symfony/symfony/pull/3479/hovercard" href="https://github.com/symfony/symfony/pull/3479">#3479</a>.</p>
<p dir="auto">The new options are:</p>
<h5 dir="auto">"choice_labels"</h5>
<p dir="auto">If given, the "choices" option is interpreted as storing the choices in the values instead of the keys. This way, choices can be created that select between values that are not allowed to be passed as array keys (any non-integer or non-string value).</p>
<p dir="auto">"choice_labels" can be:</p>
<ul dir="auto">
<li>an array with a label for each choice</li>
<li>a callable that is executed for each choice and returns the label</li>
<li>a property path string, if the choices are objects</li>
</ul>
<div class="highlight highlight-text-html-php notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&lt;?php
// The following two are equivalent
$builder-&gt;add('foo', 'choice', array(
    'choices' =&gt; array(0 =&gt; 'no', 1 =&gt; 'yes'),
));
$builder-&gt;add('foo', 'choice', array(
    'choices' =&gt; array(0, 1),
    'choice_labels' =&gt; array('no', 'yes'),
));

// The following ones cannot be expressed without the new option
$builder-&gt;add('foo', 'choice', array(
    'choices' =&gt; array(null, false, true),
    'choice_labels' =&gt; array('maybe', 'no', 'yes'),
));
$builder-&gt;add('foo', 'choice', array(
    'choices' =&gt; array($obj1, $obj2),
    'choice_labels' =&gt; 'name',
));
$builder-&gt;add('foo', 'choice', array(
    'choices' =&gt; array($obj1, $obj2),
    'choice_labels' =&gt; function ($obj) {
        return 'Label for ' . $obj-&gt;name;
    },
));"><pre class="notranslate"><span class="pl-ent">&lt;?php</span>
<span class="pl-c">// The following two are equivalent</span>
<span class="pl-s1"><span class="pl-c1">$</span>builder</span>-&gt;<span class="pl-en">add</span>(<span class="pl-s">'foo'</span>, <span class="pl-s">'choice'</span>, <span class="pl-en">array</span>(
    <span class="pl-s">'choices'</span> =&gt; <span class="pl-en">array</span>(<span class="pl-c1">0</span> =&gt; <span class="pl-s">'no'</span>, <span class="pl-c1">1</span> =&gt; <span class="pl-s">'yes'</span>),
));
<span class="pl-s1"><span class="pl-c1">$</span>builder</span>-&gt;<span class="pl-en">add</span>(<span class="pl-s">'foo'</span>, <span class="pl-s">'choice'</span>, <span class="pl-en">array</span>(
    <span class="pl-s">'choices'</span> =&gt; <span class="pl-en">array</span>(<span class="pl-c1">0</span>, <span class="pl-c1">1</span>),
    <span class="pl-s">'choice_labels'</span> =&gt; <span class="pl-en">array</span>(<span class="pl-s">'no'</span>, <span class="pl-s">'yes'</span>),
));

<span class="pl-c">// The following ones cannot be expressed without the new option</span>
<span class="pl-s1"><span class="pl-c1">$</span>builder</span>-&gt;<span class="pl-en">add</span>(<span class="pl-s">'foo'</span>, <span class="pl-s">'choice'</span>, <span class="pl-en">array</span>(
    <span class="pl-s">'choices'</span> =&gt; <span class="pl-en">array</span>(<span class="pl-c1">null</span>, <span class="pl-c1">false</span>, <span class="pl-c1">true</span>),
    <span class="pl-s">'choice_labels'</span> =&gt; <span class="pl-en">array</span>(<span class="pl-s">'maybe'</span>, <span class="pl-s">'no'</span>, <span class="pl-s">'yes'</span>),
));
<span class="pl-s1"><span class="pl-c1">$</span>builder</span>-&gt;<span class="pl-en">add</span>(<span class="pl-s">'foo'</span>, <span class="pl-s">'choice'</span>, <span class="pl-en">array</span>(
    <span class="pl-s">'choices'</span> =&gt; <span class="pl-en">array</span>(<span class="pl-s1"><span class="pl-c1">$</span>obj1</span>, <span class="pl-s1"><span class="pl-c1">$</span>obj2</span>),
    <span class="pl-s">'choice_labels'</span> =&gt; <span class="pl-s">'name'</span>,
));
<span class="pl-s1"><span class="pl-c1">$</span>builder</span>-&gt;<span class="pl-en">add</span>(<span class="pl-s">'foo'</span>, <span class="pl-s">'choice'</span>, <span class="pl-en">array</span>(
    <span class="pl-s">'choices'</span> =&gt; <span class="pl-en">array</span>(<span class="pl-s1"><span class="pl-c1">$</span>obj1</span>, <span class="pl-s1"><span class="pl-c1">$</span>obj2</span>),
    <span class="pl-s">'choice_labels'</span> =&gt; <span class="pl-k">function</span> (<span class="pl-s1"><span class="pl-c1">$</span>obj</span>) {
        <span class="pl-k">return</span> <span class="pl-s">'Label for '</span> . <span class="pl-s1"><span class="pl-c1">$</span>obj</span>-&gt;<span class="pl-c1">name</span>;
    },
));</pre></div>
<h5 dir="auto">"choice_values"</h5>
<p dir="auto">Like "choice_labels", but stores/generates the values that are stored in the "value" attributes of the generated HTML. Values  must be strings and unique (i.e. no two choices must have the same value).</p>
<p dir="auto">By default, the choices are used as values, if possible. If not possible, integer values are generated.</p>
<p dir="auto">Like "choice_labels", this option can be an array, a callable or a string (if choices are objects).</p>
<div class="highlight highlight-text-html-php notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&lt;?php
$builder-&gt;add('foo', 'choice', array(
    'choices' =&gt; array($obj1, $obj2),
    'choice_labels' =&gt; 'name',
    'choice_values' =&gt; 'id',
));"><pre class="notranslate"><span class="pl-ent">&lt;?php</span>
<span class="pl-s1"><span class="pl-c1">$</span>builder</span>-&gt;<span class="pl-en">add</span>(<span class="pl-s">'foo'</span>, <span class="pl-s">'choice'</span>, <span class="pl-en">array</span>(
    <span class="pl-s">'choices'</span> =&gt; <span class="pl-en">array</span>(<span class="pl-s1"><span class="pl-c1">$</span>obj1</span>, <span class="pl-s1"><span class="pl-c1">$</span>obj2</span>),
    <span class="pl-s">'choice_labels'</span> =&gt; <span class="pl-s">'name'</span>,
    <span class="pl-s">'choice_values'</span> =&gt; <span class="pl-s">'id'</span>,
));</pre></div>
<h5 dir="auto">"choice_attr"</h5>
<p dir="auto">Like choice_values.</p>
<h5 dir="auto">"group_by"</h5>
<p dir="auto">The "group_by" option stores a callable that returns the choice group for each choice or a property path if the choices are objects.</p>
<div class="highlight highlight-text-html-php notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&lt;?php
$builder-&gt;add('favNumber', 'choice', array(
    'choices' =&gt; range(0, 100),
    'choice_labels' =&gt; range(0, 100),
    'group_by' =&gt; function ($choice) {
        return $choice % 2 == 0 ? 'Even' : 'Odd',
    }
));"><pre class="notranslate"><span class="pl-ent">&lt;?php</span>
<span class="pl-s1"><span class="pl-c1">$</span>builder</span>-&gt;<span class="pl-en">add</span>(<span class="pl-s">'favNumber'</span>, <span class="pl-s">'choice'</span>, <span class="pl-en">array</span>(
    <span class="pl-s">'choices'</span> =&gt; range(<span class="pl-c1">0</span>, <span class="pl-c1">100</span>),
    <span class="pl-s">'choice_labels'</span> =&gt; range(<span class="pl-c1">0</span>, <span class="pl-c1">100</span>),
    <span class="pl-s">'group_by'</span> =&gt; <span class="pl-k">function</span> (<span class="pl-s1"><span class="pl-c1">$</span>choice</span>) {
        <span class="pl-k">return</span> <span class="pl-s1"><span class="pl-c1">$</span>choice</span> % <span class="pl-c1">2</span> == <span class="pl-c1">0</span> ? <span class="pl-s">'Even'</span> : <span class="pl-s">'Odd'</span>,
    }
));</pre></div>
<h5 dir="auto">"preferred_choices"</h5>
<p dir="auto">The "preferred_choices" option allows to pass the values of the preferred choices as array, a callable or a property path if the choices are objects.</p>
<div class="highlight highlight-text-html-php notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="$builder-&gt;add('foo', 'choice', array(
    'choices' =&gt; array(null, false, true),
    'choice_labels' =&gt; array('maybe', 'no', 'yes'),
    'preferred_choices' =&gt; array(true, false),
));
$builder-&gt;add('foo', 'choice', array(
    'choices' =&gt; array($obj1, $obj2),
    'preferred_choices' =&gt; 'preferred', // i.e. isPreferred()
));
$builder-&gt;add('foo', 'choice', array(
    'choices' =&gt; array($obj1, $obj2),
    'preferred_choices' =&gt; function ($obj) {
        return $obj instanceof PreferredSomething;
    },
));"><pre class="notranslate"><span class="pl-s1"><span class="pl-c1">$</span>builder</span>-&gt;<span class="pl-en">add</span>(<span class="pl-s">'foo'</span>, <span class="pl-s">'choice'</span>, <span class="pl-en">array</span>(
    <span class="pl-s">'choices'</span> =&gt; <span class="pl-en">array</span>(<span class="pl-c1">null</span>, <span class="pl-c1">false</span>, <span class="pl-c1">true</span>),
    <span class="pl-s">'choice_labels'</span> =&gt; <span class="pl-en">array</span>(<span class="pl-s">'maybe'</span>, <span class="pl-s">'no'</span>, <span class="pl-s">'yes'</span>),
    <span class="pl-s">'preferred_choices'</span> =&gt; <span class="pl-en">array</span>(<span class="pl-c1">true</span>, <span class="pl-c1">false</span>),
));
<span class="pl-s1"><span class="pl-c1">$</span>builder</span>-&gt;<span class="pl-en">add</span>(<span class="pl-s">'foo'</span>, <span class="pl-s">'choice'</span>, <span class="pl-en">array</span>(
    <span class="pl-s">'choices'</span> =&gt; <span class="pl-en">array</span>(<span class="pl-s1"><span class="pl-c1">$</span>obj1</span>, <span class="pl-s1"><span class="pl-c1">$</span>obj2</span>),
    <span class="pl-s">'preferred_choices'</span> =&gt; <span class="pl-s">'preferred'</span>, <span class="pl-c">// i.e. isPreferred()</span>
));
<span class="pl-s1"><span class="pl-c1">$</span>builder</span>-&gt;<span class="pl-en">add</span>(<span class="pl-s">'foo'</span>, <span class="pl-s">'choice'</span>, <span class="pl-en">array</span>(
    <span class="pl-s">'choices'</span> =&gt; <span class="pl-en">array</span>(<span class="pl-s1"><span class="pl-c1">$</span>obj1</span>, <span class="pl-s1"><span class="pl-c1">$</span>obj2</span>),
    <span class="pl-s">'preferred_choices'</span> =&gt; <span class="pl-k">function</span> (<span class="pl-s1"><span class="pl-c1">$</span>obj</span>) {
        <span class="pl-k">return</span> <span class="pl-s1"><span class="pl-c1">$</span>obj</span> instanceof <span class="pl-v">PreferredSomething</span>;
    },
));</pre></div>
<h4 dir="auto">Poll</h4>
<p dir="auto">If the "choices" option is given as hierarchical array sorting each choice into a choice group, there are two possible ways for associating choices with their labels/values. Which one do you prefer?</p>
<h5 dir="auto">A. Duplicate the hierarchy</h5>
<div class="highlight highlight-text-html-php notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&lt;?php
$builder-&gt;add('favNumber', 'choice', array(
    'choices' =&gt; array(
        'Even' =&gt; array($obj0, $obj2, $obj4),
        'Odd' =&gt; array($obj1, $obj3, $obj5),
    ),
    'choice_labels' =&gt; array(
        'Even' =&gt; array('Zero', 'Two', 'Four'),
        'Odd' =&gt; array('One', 'Three', 'Five'),
    ),
    'choice_values' =&gt; array(
        'Even' =&gt; array(0, 2, 4),
        'Odd' =&gt; array(1, 3, 5),
    ),
));"><pre class="notranslate"><span class="pl-ent">&lt;?php</span>
<span class="pl-s1"><span class="pl-c1">$</span>builder</span>-&gt;<span class="pl-en">add</span>(<span class="pl-s">'favNumber'</span>, <span class="pl-s">'choice'</span>, <span class="pl-en">array</span>(
    <span class="pl-s">'choices'</span> =&gt; <span class="pl-en">array</span>(
        <span class="pl-s">'Even'</span> =&gt; <span class="pl-en">array</span>(<span class="pl-s1"><span class="pl-c1">$</span>obj0</span>, <span class="pl-s1"><span class="pl-c1">$</span>obj2</span>, <span class="pl-s1"><span class="pl-c1">$</span>obj4</span>),
        <span class="pl-s">'Odd'</span> =&gt; <span class="pl-en">array</span>(<span class="pl-s1"><span class="pl-c1">$</span>obj1</span>, <span class="pl-s1"><span class="pl-c1">$</span>obj3</span>, <span class="pl-s1"><span class="pl-c1">$</span>obj5</span>),
    ),
    <span class="pl-s">'choice_labels'</span> =&gt; <span class="pl-en">array</span>(
        <span class="pl-s">'Even'</span> =&gt; <span class="pl-en">array</span>(<span class="pl-s">'Zero'</span>, <span class="pl-s">'Two'</span>, <span class="pl-s">'Four'</span>),
        <span class="pl-s">'Odd'</span> =&gt; <span class="pl-en">array</span>(<span class="pl-s">'One'</span>, <span class="pl-s">'Three'</span>, <span class="pl-s">'Five'</span>),
    ),
    <span class="pl-s">'choice_values'</span> =&gt; <span class="pl-en">array</span>(
        <span class="pl-s">'Even'</span> =&gt; <span class="pl-en">array</span>(<span class="pl-c1">0</span>, <span class="pl-c1">2</span>, <span class="pl-c1">4</span>),
        <span class="pl-s">'Odd'</span> =&gt; <span class="pl-en">array</span>(<span class="pl-c1">1</span>, <span class="pl-c1">3</span>, <span class="pl-c1">5</span>),
    ),
));</pre></div>
<h5 dir="auto">B. Array-index based</h5>
<div class="highlight highlight-text-html-php notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&lt;?php
$builder-&gt;add('favNumber', 'choice', array(
    'choices' =&gt; array(
        'Even' =&gt; array(0 =&gt; $obj0, 2 =&gt; $obj2, 4 =&gt; $obj4),
        'Odd' =&gt; array(1 =&gt; $obj1, 3 =&gt; $obj3, 5 =&gt; $obj5),
    ),
    'choice_labels' =&gt; array(
       array(0 =&gt; 'Zero', 1 =&gt; 'One', 2 =&gt; 'Two', 3 =&gt; 'Three', 4 =&gt; 'Four', 5 =&gt; 'Five'),
    ),
    'choice_values' =&gt; array(
        array(0 =&gt; 0, 1 =&gt; 1, 2 =&gt; 2, 3 =&gt; 3, 4 =&gt; 4, 5 =&gt; 5),
    ),
));"><pre class="notranslate"><span class="pl-ent">&lt;?php</span>
<span class="pl-s1"><span class="pl-c1">$</span>builder</span>-&gt;<span class="pl-en">add</span>(<span class="pl-s">'favNumber'</span>, <span class="pl-s">'choice'</span>, <span class="pl-en">array</span>(
    <span class="pl-s">'choices'</span> =&gt; <span class="pl-en">array</span>(
        <span class="pl-s">'Even'</span> =&gt; <span class="pl-en">array</span>(<span class="pl-c1">0</span> =&gt; <span class="pl-s1"><span class="pl-c1">$</span>obj0</span>, <span class="pl-c1">2</span> =&gt; <span class="pl-s1"><span class="pl-c1">$</span>obj2</span>, <span class="pl-c1">4</span> =&gt; <span class="pl-s1"><span class="pl-c1">$</span>obj4</span>),
        <span class="pl-s">'Odd'</span> =&gt; <span class="pl-en">array</span>(<span class="pl-c1">1</span> =&gt; <span class="pl-s1"><span class="pl-c1">$</span>obj1</span>, <span class="pl-c1">3</span> =&gt; <span class="pl-s1"><span class="pl-c1">$</span>obj3</span>, <span class="pl-c1">5</span> =&gt; <span class="pl-s1"><span class="pl-c1">$</span>obj5</span>),
    ),
    <span class="pl-s">'choice_labels'</span> =&gt; <span class="pl-en">array</span>(
       <span class="pl-en">array</span>(<span class="pl-c1">0</span> =&gt; <span class="pl-s">'Zero'</span>, <span class="pl-c1">1</span> =&gt; <span class="pl-s">'One'</span>, <span class="pl-c1">2</span> =&gt; <span class="pl-s">'Two'</span>, <span class="pl-c1">3</span> =&gt; <span class="pl-s">'Three'</span>, <span class="pl-c1">4</span> =&gt; <span class="pl-s">'Four'</span>, <span class="pl-c1">5</span> =&gt; <span class="pl-s">'Five'</span>),
    ),
    <span class="pl-s">'choice_values'</span> =&gt; <span class="pl-en">array</span>(
        <span class="pl-en">array</span>(<span class="pl-c1">0</span> =&gt; <span class="pl-c1">0</span>, <span class="pl-c1">1</span> =&gt; <span class="pl-c1">1</span>, <span class="pl-c1">2</span> =&gt; <span class="pl-c1">2</span>, <span class="pl-c1">3</span> =&gt; <span class="pl-c1">3</span>, <span class="pl-c1">4</span> =&gt; <span class="pl-c1">4</span>, <span class="pl-c1">5</span> =&gt; <span class="pl-c1">5</span>),
    ),
));</pre></div>
<p dir="auto">Please name your preferred option in the comments.</p>