<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>yes</td>
</tr>
<tr>
<td>RFC?</td>
<td>no</td>
</tr>
<tr>
<td>Symfony version</td>
<td>3.2.0</td>
</tr>
</tbody>
</table>
<p dir="auto">Hello,</p>
<p dir="auto">The <code class="notranslate">CurrencyType</code> isn't working the same way like in symfony 3.1.</p>
<p dir="auto">In 3.1 <code class="notranslate">CurrencyType</code> choises weren't lazy loaded but now it is. There is a problem:</p>
<p dir="auto"><a href="https://github.com/symfony/symfony/blob/3.1/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToValueTransformer.php#L46"><code class="notranslate">Symfony\Component\Form\Extension\Core\DataTransformer\ChoiceToValueTransformer</code></a>:</p>
<div class="highlight highlight-text-html-php notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="public function reverseTransform($value)
{
    if (null !== $value &amp;&amp; !is_string($value)) {
        throw new TransformationFailedException('Expected a string or null.');
    }

    $choices = $this-&gt;choiceList-&gt;getChoicesForValues(array((string) $value));

    if (1 !== count($choices)) {
        if (null === $value || '' === $value) {
            return;
        }

        throw new TransformationFailedException(sprintf('The choice &quot;%s&quot; does not exist or is not unique', $value));
    }

    return current($choices);
}"><pre class="notranslate"><span class="pl-k">public</span> <span class="pl-k">function</span> <span class="pl-en">reverseTransform</span>(<span class="pl-s1"><span class="pl-c1">$</span>value</span>)
{
    <span class="pl-k">if</span> (<span class="pl-c1">null</span> !== <span class="pl-s1"><span class="pl-c1">$</span>value</span> &amp;&amp; !is_string(<span class="pl-s1"><span class="pl-c1">$</span>value</span>)) {
        <span class="pl-k">throw</span> <span class="pl-k">new</span> <span class="pl-v">TransformationFailedException</span>(<span class="pl-s">'Expected a string or null.'</span>);
    }

    <span class="pl-s1"><span class="pl-c1">$</span>choices</span> = <span class="pl-s1"><span class="pl-c1">$</span><span class="pl-smi">this</span></span>-&gt;<span class="pl-c1">choiceList</span>-&gt;<span class="pl-en">getChoicesForValues</span>(<span class="pl-en">array</span>((<span class="pl-smi">string</span>) <span class="pl-s1"><span class="pl-c1">$</span>value</span>));

    <span class="pl-k">if</span> (<span class="pl-c1">1</span> !== count(<span class="pl-s1"><span class="pl-c1">$</span>choices</span>)) {
        <span class="pl-k">if</span> (<span class="pl-c1">null</span> === <span class="pl-s1"><span class="pl-c1">$</span>value</span> || <span class="pl-s">''</span> === <span class="pl-s1"><span class="pl-c1">$</span>value</span>) {
            <span class="pl-k">return</span>;
        }

        <span class="pl-k">throw</span> <span class="pl-k">new</span> <span class="pl-v">TransformationFailedException</span>(sprintf(<span class="pl-s">'The choice "%s" does not exist or is not unique'</span>, <span class="pl-s1"><span class="pl-c1">$</span>value</span>));
    }

    <span class="pl-k">return</span> current(<span class="pl-s1"><span class="pl-c1">$</span>choices</span>);
}</pre></div>
<p dir="auto"><code class="notranslate">$choices = $this-&gt;choiceList-&gt;getChoicesForValues(array((string) $value));</code></p>
<p dir="auto">In <code class="notranslate">3.1</code> the value of <code class="notranslate">$choices</code> equals to <code class="notranslate">[]</code> is <code class="notranslate">$value</code> isn't present in the list of choices. For example if we use <code class="notranslate">CurrencyType</code> and we'll pass 'blablabla' as <code class="notranslate">$value</code>, it will return <code class="notranslate">[]</code>.</p>
<p dir="auto">In <code class="notranslate">3.1</code> <code class="notranslate">$this-&gt;choiceList</code> is <a href="https://github.com/symfony/symfony/blob/3.1/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php#L138"><code class="notranslate">Symfony\Component\Form\ChoiceList\ArrayChoiceList</code></a>:</p>
<div class="highlight highlight-text-html-php notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="public function getChoicesForValues(array $values)
{
    $choices = array();

    foreach ($values as $i =&gt; $givenValue) {
        if (array_key_exists($givenValue, $this-&gt;choices)) {
            $choices[$i] = $this-&gt;choices[$givenValue];
        }
    }

    return $choices;
}"><pre class="notranslate"><span class="pl-k">public</span> <span class="pl-k">function</span> <span class="pl-en">getChoicesForValues</span>(<span class="pl-smi">array</span> <span class="pl-s1"><span class="pl-c1">$</span>values</span>)
{
    <span class="pl-s1"><span class="pl-c1">$</span>choices</span> = <span class="pl-en">array</span>();

    <span class="pl-k">foreach</span> (<span class="pl-s1"><span class="pl-c1">$</span>values</span> <span class="pl-k">as</span> <span class="pl-s1"><span class="pl-c1">$</span>i</span> =&gt; <span class="pl-s1"><span class="pl-c1">$</span>givenValue</span>) {
        <span class="pl-k">if</span> (array_key_exists(<span class="pl-s1"><span class="pl-c1">$</span>givenValue</span>, <span class="pl-s1"><span class="pl-c1">$</span><span class="pl-smi">this</span></span>-&gt;<span class="pl-c1">choices</span>)) {
            <span class="pl-s1"><span class="pl-c1">$</span>choices</span>[<span class="pl-s1"><span class="pl-c1">$</span>i</span>] = <span class="pl-s1"><span class="pl-c1">$</span><span class="pl-smi">this</span></span>-&gt;<span class="pl-c1">choices</span>[<span class="pl-s1"><span class="pl-c1">$</span>givenValue</span>];
        }
    }

    <span class="pl-k">return</span> <span class="pl-s1"><span class="pl-c1">$</span>choices</span>;
}</pre></div>
<p dir="auto"><code class="notranslate">if (array_key_exists($givenValue, $this-&gt;choices)) {</code> checks whether the 'blablabla' is present in the list of currencies.</p>
<p dir="auto">So the behaviour in <code class="notranslate">3.1</code> is fine. But.. Let's take a look on <code class="notranslate">3.2.0</code>:</p>
<p dir="auto"><code class="notranslate">$this-&gt;choiceList</code> in <a href="https://github.com/symfony/symfony/blob/3.2/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToValueTransformer.php#L46"><code class="notranslate">Symfony\Component\Form\Extension\Core\DataTransformer\ChoiceToValueTransformer</code></a> is <a href="https://github.com/symfony/symfony/blob/3.2/src/Symfony/Component/Form/ChoiceList/LazyChoiceList.php"><code class="notranslate">Symfony\Component\Form\ChoiceList\LazyChoiceList</code></a> that calls the following function in <a href="https://github.com/symfony/symfony/blob/3.2/src/Symfony/Component/Form/Extension/Core/Type/CurrencyType.php#L78-L92"><code class="notranslate">Symfony\Component\Form\Extension\Core\Type\CurrencyType</code></a> in this case:</p>
<div class="highlight highlight-text-html-php notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="public function loadChoicesForValues(array $values, $value = null)
{
    // Optimize
    if (empty($values)) {
        return array();
    }

    // If no callable is set, values are the same as choices
    if (null === $value) {
        return $values;
    }

    return $this-&gt;loadChoiceList($value)-&gt;getChoicesForValues($values);
}"><pre class="notranslate"><span class="pl-k">public</span> <span class="pl-k">function</span> <span class="pl-en">loadChoicesForValues</span>(<span class="pl-smi">array</span> <span class="pl-s1"><span class="pl-c1">$</span>values</span>, <span class="pl-s1"><span class="pl-c1">$</span>value</span> = <span class="pl-c1">null</span>)
{
    <span class="pl-c">// Optimize</span>
    <span class="pl-k">if</span> (empty(<span class="pl-s1"><span class="pl-c1">$</span>values</span>)) {
        <span class="pl-k">return</span> <span class="pl-en">array</span>();
    }

    <span class="pl-c">// If no callable is set, values are the same as choices</span>
    <span class="pl-k">if</span> (<span class="pl-c1">null</span> === <span class="pl-s1"><span class="pl-c1">$</span>value</span>) {
        <span class="pl-k">return</span> <span class="pl-s1"><span class="pl-c1">$</span>values</span>;
    }

    <span class="pl-k">return</span> <span class="pl-s1"><span class="pl-c1">$</span><span class="pl-smi">this</span></span>-&gt;<span class="pl-en">loadChoiceList</span>(<span class="pl-s1"><span class="pl-c1">$</span>value</span>)-&gt;<span class="pl-en">getChoicesForValues</span>(<span class="pl-s1"><span class="pl-c1">$</span>values</span>);
}</pre></div>
<p dir="auto">But <code class="notranslate">if (null === $value) {</code> happens because <a href="https://github.com/symfony/symfony/blob/3.2/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToValueTransformer.php#L46"><code class="notranslate">Symfony\Component\Form\Extension\Core\DataTransformer\ChoiceToValueTransformer</code></a> did his best to prevent this (there is no a second parameter):</p>
<p dir="auto">remember <code class="notranslate">$choices = $this-&gt;choiceList-&gt;getChoicesForValues(array((string) $value));</code>.</p>
<p dir="auto">That's all. Is it a normal behaviour? How to deal with it with minimal loses?</p>
<p dir="auto">Thank you.</p>
<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>2.8.11</td>
</tr>
</tbody>
</table>
<p dir="auto">Hello.</p>
<p dir="auto">Is it ok, when incorrect data submitted to ChoiceType and <code class="notranslate">isValid</code> returns <code class="notranslate">true</code>?</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="        $form = $this-&gt;factory-&gt;create('Symfony\Component\Form\Extension\Core\Type\ChoiceType', null, array(
            'expanded' =&gt; true
            'choices' =&gt; [
                    'a' =&gt; 'a',
                    'b' =&gt; 'b'
            ],
        ));

        $form-&gt;submit('c');
        $form-&gt;isValid(); // returns true
        $form-&gt;isSynchronized(); // returns false
        $form-&gt;getData(); // returns null"><pre class="notranslate"><code class="notranslate">        $form = $this-&gt;factory-&gt;create('Symfony\Component\Form\Extension\Core\Type\ChoiceType', null, array(
            'expanded' =&gt; true
            'choices' =&gt; [
                    'a' =&gt; 'a',
                    'b' =&gt; 'b'
            ],
        ));

        $form-&gt;submit('c');
        $form-&gt;isValid(); // returns true
        $form-&gt;isSynchronized(); // returns false
        $form-&gt;getData(); // returns null
</code></pre></div>
<p dir="auto">It actually strange that this submission is valid.<br>
It happens because ChoiceType throws <a href="https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php#L136-L139">TransformationFailedException</a> on PRE_SUBMIT event.</p>
<p dir="auto">I think in this case <code class="notranslate">isValid</code> should return <code class="notranslate">false</code>.<br>
What do you think?</p>