Skip to content

Commit cd7835d

Browse files
committed
[Form] Cached the form type hierarchy in order to improve performance
1 parent 2ca753b commit cd7835d

31 files changed

+1511
-763
lines changed

UPGRADE-2.1.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,16 @@
249249
public function finishView(FormViewInterface $view, FormInterface $form, array $options)
250250
```
251251
252+
* The method `createBuilder` was removed from `FormTypeInterface` for performance
253+
reasons. It is now not possible anymore to use custom implementations of
254+
`FormBuilderInterface` for specific form types.
255+
256+
If you are in such a situation, you can subclass `FormRegistry` instead and override
257+
`resolveType` to return a custom `ResolvedFormTypeInterface` implementation, within
258+
which you can create your own `FormBuilderInterface` implementation. You should
259+
register this custom registry class under the service name "form.registry" in order
260+
to replace the default implementation.
261+
252262
* If you previously inherited from `FieldType`, you should now inherit from
253263
`FormType`. You should also set the option `compound` to `false` if your field
254264
is not supposed to contain child fields.
@@ -1001,6 +1011,24 @@
10011011
));
10021012
```
10031013
1014+
* The methods `addType`, `hasType` and `getType` in `FormFactory` are deprecated
1015+
and will be removed in Symfony 2.3. You should use the methods with the same
1016+
name on the `FormRegistry` instead.
1017+
1018+
Before:
1019+
1020+
```
1021+
$this->get('form.factory')->addType(new MyFormType());
1022+
```
1023+
1024+
After:
1025+
1026+
```
1027+
$registry = $this->get('form.registry');
1028+
1029+
$registry->addType($registry->resolveType(new MyFormType()));
1030+
```
1031+
10041032
### Validator
10051033
10061034
* The methods `setMessage()`, `getMessageTemplate()` and

src/Symfony/Bridge/Doctrine/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ CHANGELOG
77
* added a default implementation of the ManagerRegistry
88
* added a session storage for Doctrine DBAL
99
* DoctrineOrmTypeGuesser now guesses "collection" for array Doctrine type
10+
* DoctrineType now caches its choice lists in order to improve performance

src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@
66

77
<parameters>
88
<parameter key="form.extension.class">Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension</parameter>
9+
<parameter key="form.registry.class">Symfony\Component\Form\FormRegistry</parameter>
910
<parameter key="form.factory.class">Symfony\Component\Form\FormFactory</parameter>
1011
<parameter key="form.type_guesser.validator.class">Symfony\Component\Form\Extension\Validator\ValidatorTypeGuesser</parameter>
1112
</parameters>
1213

1314
<services>
14-
<!-- FormFactory -->
15-
<service id="form.factory" class="%form.factory.class%">
15+
<!-- FormRegistry -->
16+
<service id="form.registry" class="%form.registry.class%">
1617
<argument type="collection">
1718
<!--
1819
We don't need to be able to add more extensions.
@@ -23,6 +24,11 @@
2324
</argument>
2425
</service>
2526

27+
<!-- FormFactory -->
28+
<service id="form.factory" class="%form.factory.class%">
29+
<argument type="service" id="form.registry" />
30+
</service>
31+
2632
<!-- DependencyInjectionExtension -->
2733
<service id="form.extension" class="%form.extension.class%" public="false">
2834
<argument type="service" id="service_container" />

src/Symfony/Component/Form/AbstractType.php

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@
2020
abstract class AbstractType implements FormTypeInterface
2121
{
2222
/**
23-
* The extensions for this type
24-
* @var array An array of FormTypeExtensionInterface instances
23+
* @var array
24+
*
25+
* @deprecated Deprecated since version 2.1, to be removed in 2.3.
2526
*/
2627
private $extensions = array();
2728

@@ -46,14 +47,6 @@ public function finishView(FormViewInterface $view, FormInterface $form, array $
4647
{
4748
}
4849

49-
/**
50-
* {@inheritdoc}
51-
*/
52-
public function createBuilder($name, FormFactoryInterface $factory, array $options)
53-
{
54-
return null;
55-
}
56-
5750
/**
5851
* {@inheritdoc}
5952
*/
@@ -98,21 +91,26 @@ public function getParent()
9891
}
9992

10093
/**
101-
* {@inheritdoc}
94+
* Sets the extensions for this type.
95+
*
96+
* @param array $extensions An array of FormTypeExtensionInterface
97+
*
98+
* @throws Exception\UnexpectedTypeException if any extension does not implement FormTypeExtensionInterface
99+
*
100+
* @deprecated Deprecated since version 2.1, to be removed in 2.3.
102101
*/
103102
public function setExtensions(array $extensions)
104103
{
105-
foreach ($extensions as $extension) {
106-
if (!$extension instanceof FormTypeExtensionInterface) {
107-
throw new UnexpectedTypeException($extension, 'Symfony\Component\Form\FormTypeExtensionInterface');
108-
}
109-
}
110-
111104
$this->extensions = $extensions;
112105
}
113106

114107
/**
115-
* {@inheritdoc}
108+
* Returns the extensions associated with this type.
109+
*
110+
* @return array An array of FormTypeExtensionInterface
111+
*
112+
* @deprecated Deprecated since version 2.1, to be removed in 2.3. Use
113+
* {@link ResolvedFormTypeInterface::getTypeExtensions()} instead.
116114
*/
117115
public function getExtensions()
118116
{

src/Symfony/Component/Form/CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ CHANGELOG
8686
* `hasAttribute`
8787
* `getClientData`
8888
* added FormBuilder methods
89+
* `getTypes`
8990
* `addViewTransformer`
9091
* `getViewTransformers`
9192
* `resetViewTransformers`
@@ -157,3 +158,15 @@ CHANGELOG
157158
* deprecated the options "data_timezone" and "user_timezone" in DateType, DateTimeType and TimeType
158159
and renamed them to "model_timezone" and "view_timezone"
159160
* fixed: TransformationFailedExceptions thrown in the model transformer are now caught by the form
161+
* added FormRegistry and ResolvedFormTypeInterface
162+
* deprecated FormFactory methods
163+
* `addType`
164+
* `hasType`
165+
* `getType`
166+
* [BC BREAK] FormFactory now expects a FormRegistryInterface as constructor argument
167+
* [BC BREAK] The method `createBuilder` in FormTypeInterface is not supported anymore for performance reasons
168+
* [BC BREAK] Removed `setTypes` from FormBuilder
169+
* deprecated AbstractType methods
170+
* `getExtensions`
171+
* `setExtensions`
172+
* ChoiceType now caches its created choice lists to improve performance

src/Symfony/Component/Form/Extension/Core/Type/FormType.php

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
use Symfony\Component\Form\Extension\Core\EventListener\BindRequestListener;
2121
use Symfony\Component\Form\Extension\Core\EventListener\TrimListener;
2222
use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
23-
use Symfony\Component\EventDispatcher\EventDispatcher;
2423
use Symfony\Component\Form\Exception\FormException;
2524
use Symfony\Component\OptionsResolver\Options;
2625
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
@@ -93,8 +92,8 @@ public function buildView(FormViewInterface $view, FormInterface $form, array $o
9392
}
9493

9594
$types = array();
96-
foreach ($form->getConfig()->getTypes() as $type) {
97-
$types[] = $type->getName();
95+
for ($type = $form->getConfig()->getType(); null !== $type; $type = $type->getParent()) {
96+
array_unshift($types, $type->getName());
9897
}
9998

10099
if (!$translationDomain) {
@@ -211,14 +210,6 @@ public function setDefaultOptions(OptionsResolverInterface $resolver)
211210
));
212211
}
213212

214-
/**
215-
* {@inheritdoc}
216-
*/
217-
public function createBuilder($name, FormFactoryInterface $factory, array $options)
218-
{
219-
return new FormBuilder($name, $options['data_class'], new EventDispatcher(), $factory, $options);
220-
}
221-
222213
/**
223214
* {@inheritdoc}
224215
*/

src/Symfony/Component/Form/Form.php

Lines changed: 9 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -195,11 +195,17 @@ public function getPropertyPath()
195195
* @return array An array of FormTypeInterface
196196
*
197197
* @deprecated Deprecated since version 2.1, to be removed in 2.3. Use
198-
* {@link getConfig()} and {@link FormConfigInterface::getTypes()} instead.
198+
* {@link getConfig()} and {@link FormConfigInterface::getType()} instead.
199199
*/
200200
public function getTypes()
201201
{
202-
return $this->config->getTypes();
202+
$types = array();
203+
204+
for ($type = $this->config->getType(); null !== $type; $type = $type->getParent()) {
205+
array_unshift($types, $type->getInnerType());
206+
}
207+
208+
return $types;
203209
}
204210

205211
/**
@@ -948,34 +954,7 @@ public function createView(FormViewInterface $parent = null)
948954
$parent = $this->parent->createView();
949955
}
950956

951-
$view = new FormView($this->config->getName());
952-
953-
$view->setParent($parent);
954-
955-
$types = (array) $this->config->getTypes();
956-
$options = $this->config->getOptions();
957-
958-
foreach ($types as $type) {
959-
$type->buildView($view, $this, $options);
960-
961-
foreach ($type->getExtensions() as $typeExtension) {
962-
$typeExtension->buildView($view, $this, $options);
963-
}
964-
}
965-
966-
foreach ($this->children as $child) {
967-
$view->add($child->createView($view));
968-
}
969-
970-
foreach ($types as $type) {
971-
$type->finishView($view, $this, $options);
972-
973-
foreach ($type->getExtensions() as $typeExtension) {
974-
$typeExtension->finishView($view, $this, $options);
975-
}
976-
}
977-
978-
return $view;
957+
return $this->config->getType()->createView($this, $parent);
979958
}
980959

981960
/**

src/Symfony/Component/Form/FormBuilder.php

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,10 @@ public function create($name, $type = null, array $options = array())
115115
}
116116

117117
if (null !== $type) {
118-
return $this->getFormFactory()->createNamedBuilder($name, $type, null, $options, $this);
118+
return $this->factory->createNamedBuilder($name, $type, null, $options, $this);
119119
}
120120

121-
return $this->getFormFactory()->createBuilderForProperty($this->getDataClass(), $name, null, $options, $this);
121+
return $this->factory->createBuilderForProperty($this->getDataClass(), $name, null, $options, $this);
122122
}
123123

124124
/**
@@ -266,4 +266,23 @@ public function getIterator()
266266
{
267267
return new \ArrayIterator($this->children);
268268
}
269+
270+
/**
271+
* Returns the types used by this builder.
272+
*
273+
* @return array An array of FormTypeInterface
274+
*
275+
* @deprecated Deprecated since version 2.1, to be removed in 2.3. Use
276+
* {@link FormConfigInterface::getType()} instead.
277+
*/
278+
public function getTypes()
279+
{
280+
$types = array();
281+
282+
for ($type = $this->getType(); null !== $type; $type = $type->getParent()) {
283+
array_unshift($types, $type->getInnerType());
284+
}
285+
286+
return $types;
287+
}
269288
}

src/Symfony/Component/Form/FormConfig.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ class FormConfig implements FormConfigEditorInterface
5959
private $compound = false;
6060

6161
/**
62-
* @var array
62+
* @var ResolvedFormTypeInterface
6363
*/
64-
private $types = array();
64+
private $type;
6565

6666
/**
6767
* @var array
@@ -377,9 +377,9 @@ public function getCompound()
377377
/**
378378
* {@inheritdoc}
379379
*/
380-
public function getTypes()
380+
public function getType()
381381
{
382-
return $this->types;
382+
return $this->type;
383383
}
384384

385385
/**
@@ -671,9 +671,9 @@ public function setCompound($compound)
671671
/**
672672
* {@inheritdoc}
673673
*/
674-
public function setTypes(array $types)
674+
public function setType(ResolvedFormTypeInterface $type)
675675
{
676-
$this->types = $types;
676+
$this->type = $type;
677677

678678
return $this;
679679
}

src/Symfony/Component/Form/FormConfigEditorInterface.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,11 +213,11 @@ public function setCompound($compound);
213213
/**
214214
* Set the types.
215215
*
216-
* @param array $types An array FormTypeInterface
216+
* @param ResolvedFormTypeInterface $type The type of the form.
217217
*
218218
* @return self The configuration object.
219219
*/
220-
public function setTypes(array $types);
220+
public function setType(ResolvedFormTypeInterface $type);
221221

222222
/**
223223
* Sets the initial data of the form.

0 commit comments

Comments
 (0)