This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
symfony/UPGRADE-2.3.md

306 lines
7.5 KiB
Markdown
Raw Permalink Normal View History

UPGRADE FROM 2.2 to 2.3
=======================
Form
----
* Although this was not officially supported nor documented, it was possible to
set the option "validation_groups" to false, resulting in the group "Default"
being validated. Now, if you set "validation_groups" to false, the validation
of a form will be skipped (except for a few integrity checks on the form).
If you want to validate a form in group "Default", you should either
explicitly set "validation_groups" to "Default" or alternatively set it to
null.
Before:
```
// equivalent notations for validating in group "Default"
"validation_groups" => null
"validation_groups" => "Default"
"validation_groups" => false
// notation for skipping validation
"validation_groups" => array()
```
After:
```
// equivalent notations for validating in group "Default"
"validation_groups" => null
"validation_groups" => "Default"
// equivalent notations for skipping validation
"validation_groups" => false
"validation_groups" => array()
```
* The array type hint from DataMapperInterface was removed. You should adapt
implementations of that interface accordingly.
Before:
2014-09-26 11:51:50 +01:00
```php
use Symfony\Component\Form\DataMapperInterface;
class MyDataMapper
{
public function mapFormsToData(array $forms, $data)
{
// ...
}
public function mapDataToForms($data, array $forms)
{
// ...
}
}
```
After:
2014-09-26 11:51:50 +01:00
```php
use Symfony\Component\Form\DataMapperInterface;
class MyDataMapper
{
public function mapFormsToData($forms, $data)
{
// ...
}
public function mapDataToForms($data, $forms)
{
// ...
}
}
```
Instead of an array, the methods here are now passed a
RecursiveIteratorIterator containing an InheritDataAwareIterator by default,
so you don't need to handle forms inheriting their parent data (former
"virtual forms") in the data mapper anymore.
Before:
2014-09-26 11:51:50 +01:00
```php
use Symfony\Component\Form\Util\VirtualFormAwareIterator;
public function mapFormsToData(array $forms, $data)
{
$iterator = new \RecursiveIteratorIterator(
new VirtualFormAwareIterator($forms)
);
foreach ($iterator as $form) {
// ...
}
}
```
After:
2014-09-26 11:51:50 +01:00
```php
public function mapFormsToData($forms, $data)
{
foreach ($forms as $form) {
// ...
}
}
```
2014-07-09 16:16:57 +01:00
* The `*_SET_DATA` events are now guaranteed to be fired *after* the children
were added by the FormBuilder (unless setData() is called manually). Before,
2014-07-09 16:16:57 +01:00
the `*_SET_DATA` events were sometimes thrown before adding child forms,
which made it impossible to remove child forms dynamically.
A consequence of this change is that you need to set the "auto_initialize"
option to `false` for `FormInterface` instances that you pass to
`FormInterface::add()`:
Before:
2014-09-26 11:51:50 +01:00
```php
$form = $factory->create('form');
$form->add($factory->createNamed('field', 'text'));
```
This code will now throw an exception with the following message:
Automatic initialization is only supported on root forms. You should set the
"auto_initialize" option to false on the field "field".
Consequently, you need to set the "auto_initialize" option:
After (Alternative 1):
2014-09-26 11:51:50 +01:00
```php
$form = $factory->create('form');
2013-11-26 12:30:42 +00:00
$form->add($factory->createNamed('field', 'text', array(), array(
'auto_initialize' => false,
)));
```
The problem also disappears if you work with `FormBuilder` instances instead
of `Form` instances:
After (Alternative 2):
2014-09-26 11:51:50 +01:00
```php
$builder = $factory->createBuilder('form');
$builder->add($factory->createBuilder('field', 'text'));
$form = $builder->getForm();
```
The best solution is in most cases to let `add()` handle the field creation:
After (Alternative 3):
2014-09-26 11:51:50 +01:00
```php
$form = $factory->create('form');
$form->add('field', 'text');
```
After (Alternative 4):
2014-09-26 11:51:50 +01:00
```php
$builder = $factory->createBuilder('form');
$builder->add('field', 'text');
$form = $builder->getForm();
```
* Previously, when the "data" option of a field was set to `null` and the
containing form was mapped to an object, the field would receive the data
from the object as default value. This functionality was unintended and fixed
to use `null` as default value in Symfony 2.3.
In cases where you made use of the previous behavior, you should now remove
the "data" option altogether.
Before:
2014-09-26 11:51:50 +01:00
```php
$builder->add('field', 'text', array(
'data' => $defaultData ?: null,
));
```
After:
2014-09-26 11:51:50 +01:00
```php
$options = array();
if ($defaultData) {
$options['data'] = $defaultData;
}
$builder->add('field', 'text', $options);
```
PropertyAccess
--------------
* PropertyAccessor was changed to continue its search for a property or method
even if a non-public match was found. This means that the property "author"
in the following class will now correctly be found:
2014-09-26 11:51:50 +01:00
```php
class Article
{
public $author;
private function getAuthor()
{
// ...
}
}
```
Although this is uncommon, similar cases exist in practice.
Instead of the PropertyAccessDeniedException that was thrown here, the more
generic NoSuchPropertyException is thrown now if no public property nor
method are found by the PropertyAccessor. PropertyAccessDeniedException was
removed completely.
Before:
2014-09-26 11:51:50 +01:00
```php
use Symfony\Component\PropertyAccess\Exception\PropertyAccessDeniedException;
use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
try {
$value = $accessor->getValue($article, 'author');
} catch (PropertyAccessDeniedException $e) {
// Method/property was found but not public
} catch (NoSuchPropertyException $e) {
// Method/property was not found
}
```
After:
2014-09-26 11:51:50 +01:00
```php
use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
try {
$value = $accessor->getValue($article, 'author');
} catch (NoSuchPropertyException $e) {
// Method/property was not found or not public
}
```
DomCrawler
----------
* `Crawler::each()` and `Crawler::reduce()` now return Crawler instances
instead of DomElement instances:
Before:
2014-09-26 11:51:50 +01:00
```php
$data = $crawler->each(function ($node, $i) {
return $node->nodeValue;
});
```
After:
2014-09-26 11:51:50 +01:00
```php
$data = $crawler->each(function ($crawler, $i) {
return $crawler->text();
});
```
2013-04-25 11:51:56 +01:00
Console
-------
* New verbosity levels have been added, therefore if you used to do check
the output verbosity level directly for VERBOSITY_VERBOSE you probably
want to update it to a greater than comparison:
Before:
2014-09-26 11:51:50 +01:00
```php
2013-04-25 11:51:56 +01:00
if (OutputInterface::VERBOSITY_VERBOSE === $output->getVerbosity()) { ... }
```
After:
2014-09-26 11:51:50 +01:00
```php
2013-04-25 11:51:56 +01:00
if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { ... }
```
BrowserKit
----------
* If you are receiving responses with non-3xx Status Code and Location header
please be aware that you won't be able to use auto-redirects on these kind
of responses.
If you are correctly passing 3xx Status Code with Location header, you
don't have to worry about the change.
If you were using responses with Location header and non-3xx Status Code,
you have to update your code to manually create another request to URL
2013-11-26 12:30:42 +00:00
grabbed from the Location header.