Skip to content

Commit f36fdb7

Browse files
committed
Documented FormTypeGuesserInterface
1 parent fc0aa8b commit f36fdb7

File tree

3 files changed

+148
-0
lines changed

3 files changed

+148
-0
lines changed

components/form/index.rst

+1
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@
55
:maxdepth: 2
66

77
introduction
8+
type_guesser

components/form/type_guesser.rst

+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
.. index::
2+
single: Forms; Custom Type Guesser
3+
4+
Creating a Custom Type Guesser
5+
==============================
6+
7+
The Form component can guess the type and some options of a form field by
8+
using type guessers. The component already includes a type guesser using the
9+
assertions of the Validation component, but you can also add your own custom
10+
type guessers.
11+
12+
.. sidebar:: Form Type Guessers in the Bridges
13+
14+
Symfony also provides some form type guessers in the bridges. These can be
15+
used if you use that library.
16+
17+
* :class:`Symfony\\Bridge\\Propel1\\Form\\PropelTypeGuesser` provided by
18+
the Propel1 bridge;
19+
* :class:`Symfony\\Bridge\\Doctrine\\Form\\DoctrineOrmTypeGuesser`
20+
provided by the Doctrine bridge.
21+
22+
A PHPDoc Type Guesser
23+
---------------------
24+
25+
In this section, you are going to build a PHPDoc type guesser. At first, you
26+
need to create a class which extends
27+
:class:`Symfony\\Component\\Form\\FormTypeGuesserInterface`. This interface
28+
requires 4 methods:
29+
30+
* :method:`Symfony\\Component\\Form\\FormTypeGuesserInterface::guessType` -
31+
tries to guess the type of a field;
32+
* :method:`Symfony\\Component\\Form\\FormTypeGuesserInterface::guessRequired` -
33+
tries to guess the value of the ``required`` option;
34+
* :method:`Symfony\\Component\\Form\\FormTypeGuesserInterface::guessMaxLength` -
35+
tries to guess the value of the ``max_length`` option;
36+
* :method:`Symfony\\Component\\Form\\FormTypeGuesserInterface::guessPattern` -
37+
tries to guess the value of the ``pattern`` option.
38+
39+
The most basic class looks like::
40+
41+
use Symfony\Component\Form\FormTypeGuesserInterface;
42+
43+
class PHPDocTypeGuesser implements FormTypeGuesserInterface
44+
{
45+
public function guessType($class, $property)
46+
{
47+
}
48+
49+
public function guessRequired($class, $property)
50+
{
51+
}
52+
53+
public function guessMaxLength($class, $property)
54+
{
55+
}
56+
57+
public function guessPattern($class, $property)
58+
{
59+
}
60+
}
61+
62+
Guessing the Type
63+
~~~~~~~~~~~~~~~~~
64+
65+
When guessing a type, the method returns either an instance of
66+
:class:`Symfony\\Component\\Form\\Guess\\TypeGuess` or nothing, to determine
67+
that the type guesser cannot guess the type.
68+
69+
The ``TypeGuess`` constructor requires 3 options:
70+
71+
* The type name (one of the :doc:`form types </reference/forms/types`);
72+
* Additionally options (for instance, when the type is ``entity``, you also
73+
want to set the ``class`` option). If no types are guessed, this should be
74+
set to an empty array;
75+
* The confidence that the guessed type is correct. This can be one of the
76+
constants of the :class:`Symfony\\Component\\Form\\Guess\Guess` class:
77+
``LOW_CONFIDENCE``, ``MEDIUM_CONFIDENCE``, ``HIGH_CONFIDENCE``,
78+
``VERY_HIGH_CONFIDENCE``. After all type guessers are executed, the type
79+
with the highest confidence is used.
80+
81+
With this knowledge, you can easily implement the ``guessType`` method of the
82+
``PHPDocTypeGuesser``::
83+
84+
use Symfony\Component\Form\Guess\Guess;
85+
use Symfony\Component\Form\Guess\TypeGuess;
86+
87+
// ...
88+
public function guessType($class, $property)
89+
{
90+
$annotations = $this->readPhpDocAnnotations($class, $property);
91+
92+
if (!isset($annotations['var'])) {
93+
return; // guess nothing if the @var annotation is not available
94+
}
95+
96+
// otherwise, base the type on the @var annotation
97+
switch ($annotations['var']) {
98+
case 'string':
99+
// there is a high confidence that the type is a string when
100+
// @var string is used
101+
return new TypeGuess('text', array(), Guess::HIGH_CONFIDENCE);
102+
103+
case 'int':
104+
case 'integer':
105+
// integers can also be the id of an entity or a checkbox (0 or 1)
106+
return new TypeGuess('integer', array(), Guess::MEDIUM_CONFIDENCE);
107+
108+
case 'float':
109+
case 'double':
110+
case 'real':
111+
return new TypeGuess('number', array(), Guess::MEDIUM_CONFIDENCE);
112+
113+
case 'boolean':
114+
case 'bool':
115+
return new TypeGuess('checkbox', array(), Guess::HIGH_CONFIDENCE);
116+
117+
default:
118+
// there is a very low confidence that this one is correct
119+
return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE);
120+
}
121+
}
122+
123+
This type guesser can now guess the field type for a property if it has
124+
PHPdoc!
125+
126+
Guessing Field Options
127+
~~~~~~~~~~~~~~~~~~~~~~
128+
129+
The other 3 methods (``guessMaxLength``, ``guessRequired`` and
130+
``guessPattern``) return a :class:`Symfony\\Component\\Form\\Guess\\ValueGuess`
131+
instance with the value of the option. This constructor has 2 arguments:
132+
133+
* The value of the option;
134+
* The confidence that the guessed value is correct (using the constants of the
135+
``Guess`` class).
136+
137+
``null`` is guessed when you believe the value of the option should not be
138+
set.
139+
140+
.. caution::
141+
142+
You should be very careful with the ``guessPattern`` method. When the
143+
type is a float, you cannot use it to determine a min or max value of the
144+
float (e.g. you want a float to be greater than ``5``, ``4.512313`` is not valid
145+
but ``length(4.512314) > length(5)`` is, so the pattern will success). In
146+
this case, the value should be set to ``null`` with a ``MEDIUM_CONFIDENCE``.

components/map.rst.inc

+1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
* :doc:`/components/form/index`
6969

7070
* :doc:`/components/form/introduction`
71+
* :doc:`/components/form/type_guesser`
7172

7273
* :doc:`/components/http_foundation/index`
7374

0 commit comments

Comments
 (0)