<p dir="auto">The <code class="notranslate">ValidatorTypeGuesser</code> does not consider the current form's <code class="notranslate">validation_groups</code> option when guessing type. This could be fixed by passing the options array to the guesser methods. The signature of the <code class="notranslate">FormTypeGuesserInterface</code> methods would look like this:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="function guessType($class, $property, array $options = array());"><pre class="notranslate"><code class="notranslate">function guessType($class, $property, array $options = array());
</code></pre></div>
<p dir="auto">The default argument is provided for BC.</p>
<p dir="auto">Currently, the guessing mechanism is not very efficient, because it needs to do type and metadata introspection which naturally is slow. It is also limited, because options cannot be guessed when the type is fixed in the builder.</p>
<p dir="auto">For example, assume that a property "firstName" does not have a <code class="notranslate">NotNull</code> constraint. When you do</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="$builder-&gt;add('firstName', 'text');"><pre class="notranslate"><code class="notranslate">$builder-&gt;add('firstName', 'text');
</code></pre></div>
<p dir="auto">the field will still be required, because guessing is only activated when the type parameter is omitted. To improve this status quo</p>
<ol dir="auto">
<li>guessing should be made more efficient by generating optimized guessers for model classes</li>
<li>option guessing should be activated even when the "type" parameter is given</li>
</ol>
<p dir="auto">(1) is a requirement for (2), because activating guessing for every field consequently needs a very efficient guessing mechanism.</p>
<h5 dir="auto">Implementation Suggestion</h5>
<p dir="auto">To realize the above, I suggest to add two interfaces, <code class="notranslate">FormGuesserInterface</code> and <code class="notranslate">FormGuesserStrategyInterface</code> (which replaces the current <code class="notranslate">FormTypeGuesserInterface</code>). Both are very similar, but while <code class="notranslate">FormGuesserStrategyInterface</code> returns <code class="notranslate">Guess</code> instances with confidence values about the correctness of the guessed value, <code class="notranslate">FormGuesserInterface</code> returns plain PHP values.</p>
<p dir="auto">Each form extension can optionally provide a guesser strategy, for example <code class="notranslate">ValidatorGuesserStrategy</code> and <code class="notranslate">DoctrineGuesserStrategy</code>. The form core will use a <code class="notranslate">StrategyBasedGuesser</code> that is initialized with a list of these strategies and then resolves the guesses to plain PHP values.</p>
<p dir="auto">Additionally, the form core should implement a <code class="notranslate">GeneratorBasedGuesser</code> that generates optimized PHP classes for each model class and then uses these classes for guessing. For an example see below.</p>
<h6 dir="auto">FormGuesserInterface</h6>
<div class="highlight highlight-text-html-php notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="interface FormGuesserInterface
{
    /**
     * @param string $class The class name to guess for.
     * @param string $property The property name to guess for.
     * @return string The form type to use.
     */
    public function guessType($class, $property);

    /**
     * @param string $type The used form type.
     * @param string $class The class name to guess for.
     * @param string $property The property name to guess for.
     * @return array The options to use.
     */
    public function guessOptions($type, $class, $property);
}"><pre class="notranslate"><span class="pl-k">interface</span> <span class="pl-v">FormGuesserInterface</span>
{
    <span class="pl-c">/**</span>
<span class="pl-c">     * @param string $class The class name to guess for.</span>
<span class="pl-c">     * @param string $property The property name to guess for.</span>
<span class="pl-c">     * @return string The form type to use.</span>
<span class="pl-c">     */</span>
    <span class="pl-k">public</span> <span class="pl-k">function</span> <span class="pl-en">guessType</span>(<span class="pl-s1"><span class="pl-c1">$</span>class</span>, <span class="pl-s1"><span class="pl-c1">$</span>property</span>);

    <span class="pl-c">/**</span>
<span class="pl-c">     * @param string $type The used form type.</span>
<span class="pl-c">     * @param string $class The class name to guess for.</span>
<span class="pl-c">     * @param string $property The property name to guess for.</span>
<span class="pl-c">     * @return array The options to use.</span>
<span class="pl-c">     */</span>
    <span class="pl-k">public</span> <span class="pl-k">function</span> <span class="pl-en">guessOptions</span>(<span class="pl-s1"><span class="pl-c1">$</span>type</span>, <span class="pl-s1"><span class="pl-c1">$</span>class</span>, <span class="pl-s1"><span class="pl-c1">$</span>property</span>);
}</pre></div>
<h6 dir="auto">FormGuesserStrategyInterface</h6>
<div class="highlight highlight-text-html-php notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="interface FormGuesserStrategyInterface
{
    /**
     * @param string $class The class name to guess for.
     * @param string $property The property name to guess for.
     * @return TypeGuess The form type to use together with a confidence level.
     */
    public function guessType($class, $property);

    /**
     * @param string $type The used form type.
     * @param string $class The class name to guess for.
     * @param string $property The property name to guess for.
     * @return OptionGuess[] The options to use together with confidence levels
     * and applicable form types.
     */
    public function guessOptions($type, $class, $property);
}"><pre class="notranslate"><span class="pl-k">interface</span> <span class="pl-v">FormGuesserStrategyInterface</span>
{
    <span class="pl-c">/**</span>
<span class="pl-c">     * @param string $class The class name to guess for.</span>
<span class="pl-c">     * @param string $property The property name to guess for.</span>
<span class="pl-c">     * @return TypeGuess The form type to use together with a confidence level.</span>
<span class="pl-c">     */</span>
    <span class="pl-k">public</span> <span class="pl-k">function</span> <span class="pl-en">guessType</span>(<span class="pl-s1"><span class="pl-c1">$</span>class</span>, <span class="pl-s1"><span class="pl-c1">$</span>property</span>);

    <span class="pl-c">/**</span>
<span class="pl-c">     * @param string $type The used form type.</span>
<span class="pl-c">     * @param string $class The class name to guess for.</span>
<span class="pl-c">     * @param string $property The property name to guess for.</span>
<span class="pl-c">     * @return OptionGuess[] The options to use together with confidence levels</span>
<span class="pl-c">     * and applicable form types.</span>
<span class="pl-c">     */</span>
    <span class="pl-k">public</span> <span class="pl-k">function</span> <span class="pl-en">guessOptions</span>(<span class="pl-s1"><span class="pl-c1">$</span>type</span>, <span class="pl-s1"><span class="pl-c1">$</span>class</span>, <span class="pl-s1"><span class="pl-c1">$</span>property</span>);
}</pre></div>
<h6 dir="auto">TypeGuess</h6>
<div class="highlight highlight-text-html-php notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use Symfony\Component\Form\Guess\Guess;

class TypeGuess extends Guess
{
     /**
      * @return string The guessed type.
      */
     public function getType();
}"><pre class="notranslate"><span class="pl-k">use</span> <span class="pl-v">Symfony</span>\<span class="pl-v">Component</span>\<span class="pl-v">Form</span>\<span class="pl-v">Guess</span>\<span class="pl-v">Guess</span>;

<span class="pl-k">class</span> <span class="pl-v">TypeGuess</span> <span class="pl-k">extends</span> <span class="pl-v">Guess</span>
{
     <span class="pl-c">/**</span>
<span class="pl-c">      * @return string The guessed type.</span>
<span class="pl-c">      */</span>
     <span class="pl-k">public</span> <span class="pl-k">function</span> <span class="pl-en">getType</span>();
}</pre></div>
<h6 dir="auto">OptionGuess</h6>
<div class="highlight highlight-text-html-php notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use Symfony\Component\Form\Guess\Guess;

class OptionGuess extends Guess
{
     /**
      * @return string The option name.
      */
     public function getOption();

     /**
      * @return string The guessed option value.
      */
     public function getValue();

     /**
      * @return string[] The applicable form types.
      */
     public function getApplicableTypes();
}"><pre class="notranslate"><span class="pl-k">use</span> <span class="pl-v">Symfony</span>\<span class="pl-v">Component</span>\<span class="pl-v">Form</span>\<span class="pl-v">Guess</span>\<span class="pl-v">Guess</span>;

<span class="pl-k">class</span> <span class="pl-v">OptionGuess</span> <span class="pl-k">extends</span> <span class="pl-v">Guess</span>
{
     <span class="pl-c">/**</span>
<span class="pl-c">      * @return string The option name.</span>
<span class="pl-c">      */</span>
     <span class="pl-k">public</span> <span class="pl-k">function</span> <span class="pl-en">getOption</span>();

     <span class="pl-c">/**</span>
<span class="pl-c">      * @return string The guessed option value.</span>
<span class="pl-c">      */</span>
     <span class="pl-k">public</span> <span class="pl-k">function</span> <span class="pl-en">getValue</span>();

     <span class="pl-c">/**</span>
<span class="pl-c">      * @return string[] The applicable form types.</span>
<span class="pl-c">      */</span>
     <span class="pl-k">public</span> <span class="pl-k">function</span> <span class="pl-en">getApplicableTypes</span>();
}</pre></div>
<h6 dir="auto">Generated Guesser Example</h6>
<div class="highlight highlight-text-html-php notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// Generated guesser for the &quot;Person&quot; model class
class PersonGuesser implements ClassSpecificFormGuesserInterface
{
    public function guessType($property)
    {
        switch ($property) {
            case 'gender':
                return 'choice';
            default:
                return 'text';
        }
    }

    public function guessOptions($type, $property)
    {
        switch ($property) {
            case 'gender':
                return array(
                    'required' =&gt; true,
                    'choices' =&gt; array('male', 'female'),
                );
            case 'firstName':
                return array(
                    'required' =&gt; false,
                );
            default:
                return array();
        }
    }
}"><pre class="notranslate"><span class="pl-c">// Generated guesser for the "Person" model class</span>
<span class="pl-k">class</span> <span class="pl-v">PersonGuesser</span> <span class="pl-k">implements</span> <span class="pl-v">ClassSpecificFormGuesserInterface</span>
{
    <span class="pl-k">public</span> <span class="pl-k">function</span> <span class="pl-en">guessType</span>(<span class="pl-s1"><span class="pl-c1">$</span>property</span>)
    {
        <span class="pl-k">switch</span> (<span class="pl-s1"><span class="pl-c1">$</span>property</span>) {
            <span class="pl-k">case</span> <span class="pl-s">'gender'</span>:
                <span class="pl-k">return</span> <span class="pl-s">'choice'</span>;
            <span class="pl-k">default</span>:
                <span class="pl-k">return</span> <span class="pl-s">'text'</span>;
        }
    }

    <span class="pl-k">public</span> <span class="pl-k">function</span> <span class="pl-en">guessOptions</span>(<span class="pl-s1"><span class="pl-c1">$</span>type</span>, <span class="pl-s1"><span class="pl-c1">$</span>property</span>)
    {
        <span class="pl-k">switch</span> (<span class="pl-s1"><span class="pl-c1">$</span>property</span>) {
            <span class="pl-k">case</span> <span class="pl-s">'gender'</span>:
                <span class="pl-k">return</span> <span class="pl-en">array</span>(
                    <span class="pl-s">'required'</span> =&gt; <span class="pl-c1">true</span>,
                    <span class="pl-s">'choices'</span> =&gt; <span class="pl-en">array</span>(<span class="pl-s">'male'</span>, <span class="pl-s">'female'</span>),
                );
            <span class="pl-k">case</span> <span class="pl-s">'firstName'</span>:
                <span class="pl-k">return</span> <span class="pl-en">array</span>(
                    <span class="pl-s">'required'</span> =&gt; <span class="pl-c1">false</span>,
                );
            <span class="pl-k">default</span>:
                <span class="pl-k">return</span> <span class="pl-en">array</span>();
        }
    }
}</pre></div>