-
The merging strategy for
assets_base_urlsandbase_urlshas changed.Unlike most configuration blocks, successive values for
assets_base_urlswill overwrite each other instead of being merged. This behavior was chosen because developers will typically define base URL's for each environment. Given that most projects tend to inherit configurations (e.g.config_test.ymlimportsconfig_dev.yml) and/or share a common base configuration (i.e.config.yml), merging could yield a set of base URL's for multiple environments. -
The priorities for the built-in listeners have changed.
2.0 2.1 security.firewall kernel.request 64 8 locale listener kernel.request 0 16 router listener early_request 255 n/a request 0 32
### Doctrine
* The DoctrineBundle is moved from the Symfony repository to the Doctrine repository.
Therefore you should change the namespace of this bundle in your AppKernel.php:
Before: `new Symfony\Bundle\DoctrineBundle\DoctrineBundle()`
After: `new Doctrine\Bundle\DoctrineBundle\DoctrineBundle()`
### HttpFoundation
* Locale management was moved from the Session class to the Request class.
##### Configuring the default locale
Before:
```yaml
framework:
session:
default_locale: fr
```
After:
```yaml
framework:
default_locale: fr
```
##### Retrieving the locale from a Twig template
Before: `{{ app.request.session.locale }}` or `{{ app.session.locale }}`
After: `{{ app.request.locale }}`
##### Retrieving the locale from a PHP template
Before: `$view['session']->getLocale()`
After: `$view['request']->getLocale()`
##### Retrieving the locale from PHP code
Before: `$session->getLocale()`
After: `$request->getLocale()`
##### Simulate old behavior
You can simulate that the locale for the user is still stored in the session by
registering a listener that looks like the following if the parameter which
handles the locale value in the request is `_locale`:
```php
namespace XXX;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class LocaleListener implements EventSubscriberInterface
{
private $defaultLocale;
public function __construct($defaultLocale = 'en')
{
$this->defaultLocale = $defaultLocale;
}
public function onKernelRequest(GetResponseEvent $event)
{
$request = $event->getRequest();
if (!$request->hasPreviousSession()) {
return;
}
if ($locale = $request->attributes->get('_locale')) {
$request->getSession()->set('_locale', $locale);
} else {
$request->setLocale($request->getSession()->get('_locale', $this->defaultLocale));
}
}
static public function getSubscribedEvents()
{
return array(
// must be registered before the default Locale listener
KernelEvents::REQUEST => array(array('onKernelRequest', 17)),
);
}
}- The methods
getPathInfo(),getBaseUrl()andgetBasePath()of aRequestnow all return a raw value (vs a urldecoded value before). Any call to one of these methods must be checked and wrapped in arawurldecode()if needed.
-
Symfony\Component\Security\Core\User\UserInterface::equals()has moved toSymfony\Component\Security\Core\User\EquatableInterface::isEqualTo().You must rename the
equals()method in your implementation of theUserclass toisEqualTo()and implementEquatableInterface. Apart from that, no other changes are required.Alternatively, you may use the default implementation provided by
AbstractToken::hasUserChanged()if you have no need of custom comparison logic. In this case, do not implementEquatableInterfaceand remove your comparison method.Before:
class User implements UserInterface { // ... public function equals(UserInterface $user) { /* ... */ } // ... }
After:
class User implements UserInterface, EquatableInterface { // ... public function isEqualTo(UserInterface $user) { /* ... */ } // ... }
-
The custom factories for the firewall configuration are now registered during the build method of bundles instead of being registered by the end-user. This means that you will need to remove the 'factories' keys in your security configuration.
Before:
security: factories: - "%kernel.root_dir%/../src/Acme/DemoBundle/Resources/config/security_factories.yml"
# src/Acme/DemoBundle/Resources/config/security_factories.yml services: security.authentication.factory.custom: class: Acme\DemoBundle\DependencyInjection\Security\Factory\CustomFactory tags: - { name: security.listener.factory }
After:
namespace Acme\DemoBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; use Symfony\Component\DependencyInjection\ContainerBuilder; use Acme\DemoBundle\DependencyInjection\Security\Factory\CustomFactory; class AcmeDemoBundle extends Bundle { public function build(ContainerBuilder $container) { parent::build($container); $extension = $container->getExtension('security'); $extension->addSecurityListenerFactory(new CustomFactory()); } }
-
The Firewall listener is now registered after the Router listener. This means that specific Firewall URLs (like /login_check and /logout) must now have proper routes defined in your routing configuration. Also, if you have a custom 404 error page, make sure that you do not use any security related features such as
is_grantedon it. -
The user provider configuration has been refactored. The configuration for the chain provider and the memory provider has been changed:
Before:
security: providers: my_chain_provider: providers: [my_memory_provider, my_doctrine_provider] my_memory_provider: users: toto: { password: foobar, roles: [ROLE_USER] } foo: { password: bar, roles: [ROLE_USER, ROLE_ADMIN] }
After:
security: providers: my_chain_provider: chain: providers: [my_memory_provider, my_doctrine_provider] my_memory_provider: memory: users: toto: { password: foobar, roles: [ROLE_USER] } foo: { password: bar, roles: [ROLE_USER, ROLE_ADMIN] }
-
MutableAclInterface::setParentAclnow acceptsnull, review any implementations of this interface to reflect this change. -
The
UserPasswordconstraint has moved from the Security Bundle to the Security Component:Before:
use Symfony\Bundle\SecurityBundle\Validator\Constraint\UserPassword; use Symfony\Bundle\SecurityBundle\Validator\Constraint as SecurityAssert;
After:
use Symfony\Component\Security\Core\Validator\Constraint\UserPassword; use Symfony\Component\Security\Core\Validator\Constraint as SecurityAssert;
-
A third argument
$optionswas added to the methodsbuildView()andbuildViewBottomUp()inFormTypeInterfaceandFormTypeExtensionInterface. Furthermore,buildViewBottomUp()was renamed tofinishView(). At last, all methods in these types now receive instances ofFormBuilderInterfacewhere they received instances ofFormBuilderbefore. You need to change the method signatures in your form types and extensions as shown below.Before:
use Symfony\Component\Form\FormBuilder; public function buildForm(FormBuilder $builder, array $options)
After:
use Symfony\Component\Form\FormBuilderInterface; public function buildForm(FormBuilderInterface $builder, array $options)
-
The method
createBuilderwas removed fromFormTypeInterfacefor performance reasons. It is now not possible anymore to use custom implementations ofFormBuilderInterfacefor specific form types.If you are in such a situation, you can implement a custom
ResolvedFormTypeInterfacewhere you create your ownFormBuilderInterfaceimplementation. You also need to register a customResolvedFormTypeFactoryInterfaceimplementation under the service name "form.resolved_type_factory" in order to replace the default implementation. -
If you previously inherited from
FieldType, you should now inherit fromFormType. You should also set the optioncompoundtofalseif your field is not supposed to contain child fields.FieldTypewas deprecated and will be removed in Symfony 2.3.Before:
public function getParent(array $options) { return 'field'; }
After:
public function getParent() { return 'form'; } public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'compound' => false, )); }
The changed signature of
getParent()is explained in the next step. The new methodsetDefaultOptionsis described in the section "Deprecations". -
No options are passed to
getParent()ofFormTypeInterfaceanymore. If you previously dynamically inherited fromFormTypeorFieldType, you can now dynamically set the "compound" option instead.Before:
public function getParent(array $options) { return $options['expanded'] ? 'form' : 'field'; }
After:
use Symfony\Component\OptionsResolver\OptionsResolverInterface; use Symfony\Component\OptionsResolver\Options; public function setDefaultOptions(OptionsResolverInterface $resolver) { $compound = function (Options $options) { return $options['expanded']; }; $resolver->setDefaults(array( 'compound' => $compound, )); } public function getParent() { return 'form'; }
The new method
setDefaultOptionsis described in the section "Deprecations". -
The "data_class" option now must be set if a form maps to an object. If you leave it empty, the form will expect an array, an instance of \ArrayAccess or a scalar value and fail with a corresponding exception.
Likewise, if a form maps to an array or an instance of \ArrayAccess, the option must be left null now.
Form mapped to an instance of
Person:use Symfony\Component\OptionsResolver\OptionsResolverInterface; public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'Acme\Demo\Person', )); }
-
The mapping of property paths to arrays has changed.
Previously, a property path "street" mapped to both a field
$streetof a class (or its accessorsgetStreet()andsetStreet()) and an index['street']of an array or an object implementing\ArrayAccess.Now, the property path "street" only maps to a class field (or accessors), while the property path "[street]" only maps to indices.
If you defined property paths manually in the "property_path" option, you should revise them and adjust them if necessary.
Before:
$builder->add('name', 'text', array( 'property_path' => 'address.street', ));
After (if the address object is an array):
$builder->add('name', 'text', array( 'property_path' => 'address[street]', ));
If address is an object in this case, the code given in "Before" works without changes.
-
Form and field names must now start with a letter, digit or underscore and only contain letters, digits, underscores, hyphens and colons.
-
In the collection type's template, the default name of the prototype field has changed from
$$name$$to__name__.You can now customize the name of the prototype field by changin the "prototype_name" option. You are advised to prepend and append two underscores wherever you specify a value for the field's "prototype_name" option.
$builder->add('tags', 'collection', array('prototype_name' => '__proto__')); // results in the name "__proto__" in the template
-
The "read_only" option now renders as
readonly="readonly", use "disabled" instead fordisabled="disabled". -
Child forms are no longer automatically validated. That means that you must explicitly set the
Validconstraint in your model if you want to validate objects modified by child forms.If you don't want to set the
Validconstraint, or if there is no reference from the data of the parent form to the data of the child form, you can enable BC behavior by setting the "cascade_validation" option totrueon the parent form.
-
FormType and FieldType were merged and require you to adapt your form themes.
The block
field_widgetand all references to it should be renamed toform_widget_simple:Before:
{% block url_widget %} {% spaceless %} {% set type = type|default('url') %} {{ block('field_widget') }} {% endspaceless %} {% endblock url_widget %}
After:
{% block url_widget %} {% spaceless %} {% set type = type|default('url') %} {{ block('form_widget_simple') }} {% endspaceless %} {% endblock url_widget %}
All other
field_*blocks and references to them should be renamed toform_*. If you previously defined both afield_*and aform_*block, you can merge them into a singleform_*block and check the new Boolean variablecompoundinstead:Before:
{% block form_errors %} {% spaceless %} ... form code ... {% endspaceless %} {% endblock form_errors %} {% block field_errors %} {% spaceless %} ... field code ... {% endspaceless %} {% endblock field_errors %}
After:
{% block form_errors %} {% spaceless %} {% if compound %} ... form code ... {% else %} ... field code ... {% endif %} {% endspaceless %} {% endblock form_errors %}
Furthermore, the block
generic_labelwas merged intoform_label. You should now overrideform_labelin order to customize labels.Last but not least, the block
widget_choice_optionswas renamed tochoice_widget_optionsto be consistent with the rest of the default theme. -
The strategy for generating the
idandnameHTML attributes for checkboxes and radio buttons in a choice field has changed.Instead of appending the choice value, a generated integer is now appended by default. Take care if your JavaScript relies on that. If you want to read the actual choice value, read the
valueattribute instead. -
In the choice field type's template, the
_form_is_choice_selectedmethod used to identify a selected choice has been replaced with theselectedchoicefilter. Similarly, the_form_is_choice_groupmethod used to check if a choice is grouped has been removed and can be checked with theiterabletest.Before:
{% for choice, label in choices %} {% if _form_is_choice_group(label) %} <optgroup label="{{ choice|trans }}"> {% for nestedChoice, nestedLabel in label %} ... options tags ... {% endfor %} </optgroup> {% else %} <option value="{{ choice }}"{% if _form_is_choice_selected(form, choice) %} selected="selected"{% endif %}> {{ label }} </option> {% endif %} {% endfor %}
After:
{% for label, choice in choices %} {% if choice is iterable %} <optgroup label="{{ label|trans({}, translation_domain) }}"> {% for nestedChoice, nestedLabel in choice %} ... options tags ... {% endfor %} </optgroup> {% else %} <option value="{{ choice.value }}"{% if choice is selectedchoice(value) %} selected="selected"{% endif %}> {{ label }} </option> {% endif %} {% endfor %}
-
Creation of default labels has been moved to the view layer. You will need to incorporate this logic into any custom
form_labeltemplates to accommodate those cases when thelabeloption has not been explicitly set.{% block form_label %} {% if label is empty %} {% set label = name|humanize %} {% endif %} {# ... #} {% endblock %}
-
Custom styling of individual rows of a collection form has been removed for performance reasons. Instead, all rows now have the same block name, where the word "entry" replaces the previous occurrence of the row index.
Before:
{% block _author_tags_0_label %} {# ... #} {% endblock %} {% block _author_tags_1_label %} {# ... #} {% endblock %}
After:
{% block _author_tags_entry_label %} {# ... #} {% endblock %}
-
The method
renderBlock()of the helper for the PHP Templating component was renamed toblock(). Its first argument is now expected to be aFormViewinstance.Before:
<?php echo $view['form']->renderBlock('widget_attributes') ?>
After:
<?php echo $view['form']->block($form, 'widget_attributes') ?>
-
The order of the first two arguments of the methods
createNamedandcreateNamedBuilderinFormFactoryInterfacewas reversed to be consistent with the rest of the component. You should scan your code for occurrences of these methods and reverse the parameters.Before:
$form = $factory->createNamed('text', 'firstName');
After:
$form = $factory->createNamed('firstName', 'text');
-
The implementation of
ChoiceListwas changed heavily. As a result,ArrayChoiceListwas replaced. If you have custom classes that extend this class, you must now extendSimpleChoiceListand pass choices to the parent constructor.Before:
class MyChoiceList extends ArrayChoiceList { protected function load() { parent::load(); // load choices $this->choices = $choices; } }
After:
class MyChoiceList extends SimpleChoiceList { public function __construct() { // load choices parent::__construct($choices); } }
If you need to load the choices lazily -- that is, as soon as they are accessed for the first time -- you can extend
LazyChoiceListinstead and load the choices by overridingloadChoiceList().class MyChoiceList extends LazyChoiceList { protected function loadChoiceList() { // load choices return new SimpleChoiceList($choices); } }
PaddedChoiceList,MonthChoiceListandTimezoneChoiceListwere removed. Their functionality was merged intoDateType,TimeTypeandTimezoneType.EntityChoiceListwas adapted. The methodsgetEntities(),getEntitiesByKeys(),getIdentifier()andgetIdentifierValues()were removed or made private. Instead of the first two, you can now usegetChoices()andgetChoicesByValues(). For the latter two, no replacement exists. -
HTML attributes are now passed in the
label_attrvariable for theform_labelfunction.Before:
{{ form_label(form.name, 'Your Name', { 'attr': {'class': 'foo'} }) }}After:
{{ form_label(form.name, 'Your Name', { 'label_attr': {'class': 'foo'} }) }} -
EntitiesToArrayTransformerandEntityToIdTransformerwere removed. The former was replaced byCollectionToArrayTransformerin combination withEntityChoiceList, the latter is not required in the core anymore. -
The following transformers were renamed:
ArrayToBooleanChoicesTransformertoChoicesToBooleanArrayTransformerScalarToBooleanChoicesTransformertoChoiceToBooleanArrayTransformerArrayToChoicesTransformertoChoicesToValuesTransformerScalarToChoiceTransformertoChoiceToValueTransformer
to be consistent with the naming in
ChoiceListInterface. -
FormUtil::toArrayKey()andFormUtil::toArrayKeys()were removed. They were merged into ChoiceList and have no public equivalent anymore. -
The
add(),remove(),setParent(),bind()andsetData()methods in the Form class now throw an exception if the form is already bound.If you used these methods on bound forms, you should consider moving your logic to an event listener that observes
FormEvents::PRE_BINDorFormEvents::BIND.
-
The following methods of
FormTypeInterfaceandFormTypeExtensionInterfaceare deprecated and will be removed in Symfony 2.3:getDefaultOptionsgetAllowedOptionValues
You should use the newly added
setDefaultOptionsinstead, which gives you access to the OptionsResolverInterface instance and with that a lot more power.Before:
public function getDefaultOptions(array $options) { return array( 'gender' => 'male', ); } public function getAllowedOptionValues(array $options) { return array( 'gender' => array('male', 'female'), ); }
After:
public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'gender' => 'male', )); $resolver->setAllowedValues(array( 'gender' => array('male', 'female'), )); }
You can specify options that depend on other options using closures.
Before:
public function getDefaultOptions(array $options) { $defaultOptions = array(); if ($options['multiple']) { $defaultOptions['empty_data'] = array(); } return $defaultOptions; }
After:
public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'empty_data' => function (Options $options, $value) { return $options['multiple'] ? array() : $value; } )); }
The second argument
$valuecontains the current default value and does not have to be specified if not needed. -
The following methods in
FormBuilderwere deprecated and have a new equivalent:prependClientTransformer:addViewTransformer, withtrueas second argumentappendClientTransformer:addViewTransformergetClientTransformers:getViewTransformersresetClientTransformers:resetViewTransformersprependNormTransformer:addModelTransformerappendNormTransformer:addModelTransformer, withtrueas second argumentgetNormTransformers:getModelTransformersresetNormTransformers:resetModelTransformers
The deprecated methods will be removed in Symfony 2.3. You are advised to update your application.
Before:
$builder->appendClientTransformer(new MyTransformer());
After:
$builder->addViewTransformer(new MyTransformer());
-
The following events were deprecated and have a new equivalent:
FormEvents::SET_DATA:FormEvents::PRE_SET_DATAFormEvents::BIND_CLIENT_DATA:FormEvents::PRE_BINDFormEvents::BIND_NORM_DATA:FormEvents::BIND
The deprecated events will be removed in Symfony 2.3.
Furthermore, the event classes
DataEventandFilterDataEventwere deprecated and replaced by the genericFormEvent. You are advised to code your listeners against the new event now. The deprecated events will be removed in Symfony 2.3.Before:
$builder->addListener(FormEvents::BIND_CLIENT_DATA, function (FilterDataEvent $event) { // ... });
After:
$builder->addListener(FormEvents::PRE_BIND, function (FormEvent $event) { // ... });
-
The interface
FormValidatorInterfacewas deprecated and will be removed in Symfony 2.3.If you implemented custom validators using this interface, you can substitute them by event listeners listening to the
FormEvents::POST_BIND(or any other of the*BINDevents). In case you used the CallbackValidator class, you should now pass the callback directly toaddEventListener. -
The method
guessMinLength()ofFormTypeGuesserInterfacewas deprecated and will be removed in Symfony 2.3. You should use the new methodguessPattern()instead which may return any regular expression that is inserted in the HTML5 attributepattern.Before:
public function guessMinLength($class, $property) { if (/* condition */) { return new ValueGuess($minLength, Guess::LOW_CONFIDENCE); } }
After:
public function guessPattern($class, $property) { if (/* condition */) { return new ValueGuess('.{'.$minLength.',}', Guess::LOW_CONFIDENCE); } }
-
Setting the option "property_path" to
falsewas deprecated and will be unsupported as of Symfony 2.3.You should use the new option "mapped" instead in order to set that you don't want a field to be mapped to its parent's data.
Before:
$builder->add('termsAccepted', 'checkbox', array( 'property_path' => false, ));
After:
$builder->add('termsAccepted', 'checkbox', array( 'mapped' => false, ));
-
The following methods in
Formwere deprecated and will be removed in Symfony 2.3:getTypesgetErrorBubblinggetNormTransformersgetClientTransformersgetAttributehasAttributegetClientDatagetChildrenhasChildrenbindRequest
Before:
$form->getErrorBubbling()
After:
$form->getConfig()->getErrorBubbling();
The method
getClientDatahas a new equivalent that is namedgetViewData. You can access all other methods on theFormConfigInterfaceobject instead.Instead of
getChildrenandhasChildren, you should now useallandcount.Before:
if ($form->hasChildren()) {
After:
if (count($form) > 0) {
Instead of
bindRequest, you should now simply callbind:Before:
$form->bindRequest($request);
After:
$form->bind($request);
-
The option "validation_constraint" was deprecated and will be removed in Symfony 2.3. You should use the option "constraints" instead, where you can pass one or more constraints for a form.
Before:
$builder->add('name', 'text', array( 'validation_constraint' => new NotBlank(), ));
After:
$builder->add('name', 'text', array( 'constraints' => new NotBlank(), ));
Unlike previously, you can also pass a list of constraints now:
$builder->add('name', 'text', array( 'constraints' => array( new NotBlank(), new MinLength(3), ), ));
Be aware that constraints will now only be validated if they belong to the validated group! So if you validate a form in group "Custom" and previously did:
$builder->add('name', 'text', array( 'validation_constraint' => new NotBlank(), ));
Then you need to add the constraint to the group "Custom" now:
$builder->add('name', 'text', array( 'constraints' => new NotBlank(array('groups' => 'Custom')), ));
-
The options "data_timezone" and "user_timezone" in
DateType,DateTimeTypeandTimeTypewere deprecated and will be removed in Symfony 2.3. They were renamed to "model_timezone" and "view_timezone".Before:
$builder->add('scheduledFor', 'date', array( 'data_timezone' => 'UTC', 'user_timezone' => 'America/New_York', ));
After:
$builder->add('scheduledFor', 'date', array( 'model_timezone' => 'UTC', 'view_timezone' => 'America/New_York', ));
-
The methods
addType,hasTypeandgetTypeinFormFactoryare deprecated and will be removed in Symfony 2.3. You should use the methods with the same name on theFormRegistryinstead.Before:
$this->get('form.factory')->addType(new MyFormType());
After:
$registry = $this->get('form.registry'); $registry->addType($registry->resolveType(new MyFormType()));
-
The following methods in class
FormViewwere deprecated and will be removed in Symfony 2.3:sethasgetallgetVarsaddChildgetChildgetChildrenremoveChildhasChildhasChildrengetParenthasParentsetParent
You should access the public properties
vars,childrenandparentinstead.Before:
$view->set('help', 'A text longer than six characters'); $view->set('error_class', 'max_length_error');
After:
$view->vars = array_replace($view->vars, array( 'help' => 'A text longer than six characters', 'error_class' => 'max_length_error', ));
Before:
echo $view->get('error_class');
After:
echo $view->vars['error_class'];
Before:
if ($view->hasChildren()) { ...
After:
if (count($view->children)) { ...
-
The methods
setMessage(),getMessageTemplate()andgetMessageParameters()in theConstraintValidatorclass were deprecated and will be removed in Symfony 2.3.If you have implemented custom validators, you should use the
addViolation()method on theExecutionContextobject instead.Before:
public function isValid($value, Constraint $constraint) { // ... if (!$valid) { $this->setMessage($constraint->message, array( '{{ value }}' => $value, )); return false; } }
After:
public function isValid($value, Constraint $constraint) { // ... if (!$valid) { $this->context->addViolation($constraint->message, array( '{{ value }}' => $value, )); return false; } }
-
The method
setPropertyPath()in the ExecutionContext class was removed.You should use the
addViolationAtSubPath()method on theExecutionContextobject instead.Before:
public function isPropertyValid(ExecutionContext $context) { // ... $propertyPath = $context->getPropertyPath().'.property'; $context->setPropertyPath($propertyPath); $context->addViolation('Error Message', array(), null); }
After:
public function isPropertyValid(ExecutionContext $context) { // ... $context->addViolationAtSubPath('property', 'Error Message', array(), null); }
-
The method
isValidofConstraintValidatorInterfacewas renamed tovalidateand its return value was dropped.ConstraintValidatorstill contains the deprecatedisValidmethod and forwardsvalidatecalls toisValidby default. This BC layer will be removed in Symfony 2.3. You are advised to rename your methods. You should also remove the return values, which have never been used by the framework.Before:
public function isValid($value, Constraint $constraint) { // ... if (!$valid) { $this->context->addViolation($constraint->message, array( '{{ value }}' => $value, )); return false; } }
After:
public function validate($value, Constraint $constraint) { // ... if (!$valid) { $this->context->addViolation($constraint->message, array( '{{ value }}' => $value, )); return; } }
-
Core translation messages changed. A dot is added at the end of each message. Overwritten core translations need to be fixed.
-
Collections (arrays or instances of
\Traversable) in properties annotated withValidare not traversed recursively by default anymore.This means that if a collection contains an entry which is again a collection, the inner collection won't be traversed anymore as it happened before. You can set the BC behavior by setting the new property
deepofValidtotrue.Before:
/** @Assert\Valid */ private $recursiveCollection;
After:
/** @Assert\Valid(deep = true) */ private $recursiveCollection;
-
The
Size,MinandMaxconstraints were deprecated and will be removed in Symfony 2.3. You should use the new constraintRangeinstead.Before:
/** @Assert\Size(min = 2, max = 16) */ private $numberOfCpus;
After:
/** @Assert\Range(min = 2, max = 16) */ private $numberOfCpus;
Before:
/** @Assert\Min(2) */ private $numberOfCpus;
After:
/** @Assert\Range(min = 2) */ private $numberOfCpus;
-
The
MinLengthandMaxLengthconstraints were deprecated and will be removed in Symfony 2.3. You should use the new constraintLengthinstead.Before:
/** @Assert\MinLength(8) */ private $password;
After:
/** @Assert\Length(min = 8) */ private $password;
-
The classes
ValidatorContextandValidatorFactorywere deprecated and will be removed in Symfony 2.3. You should use the new entry pointValidationinstead.Before:
$validator = ValidatorFactory::buildDefault(array('path/to/mapping.xml')) ->getValidator();
After:
$validator = Validation::createValidatorBuilder() ->addXmlMapping('path/to/mapping.xml') ->getValidator();
-
The namespace of the Session class changed from
Symfony\Component\HttpFoundation\SessiontoSymfony\Component\HttpFoundation\Session\Session. -
Using
getto retrieve flash messages now returns an array.Before:
{% if app.session.hasFlash('notice') %} <div class="flash-notice"> {{ app.session.getFlash('notice') }} </div> {% endif %}
After:
{% for flashMessage in app.session.flashbag.get('notice') %} <div class="flash-notice"> {{ flashMessage }} </div> {% endfor %}
You can process all flash messages in a single loop with:
{% for type, flashMessages in app.session.flashbag.all() %} {% for flashMessage in flashMessages %} <div class="flash-{{ type }}"> {{ flashMessage }} </div> {% endfor %} {% endfor %}
-
Session handler drivers should implement
\SessionHandlerInterfaceor extend fromSymfony\Component\HttpFoundation\Session\Storage\Handler\NativeHandlerInterfacebase class and renamed toHandler\FooSessionHandler. E.g.PdoSessionStoragebecomesHandler\PdoSessionHandler. -
Refactor code using
$session->*flash*()methods to use$session->getFlashBag()->*().
-
The key names created by the
GetSetMethodNormalizerhave changed from all lowercased to camelCased (e.g.mypropertyvaluetomyPropertyValue). -
The
itemelement is now converted to an array when deserializing XML.<?xml version="1.0"?> <response> <item><title><![CDATA[title1]]></title></item><item><title><![CDATA[title2]]></title></item> </response>
Before:
Array()
After:
Array( [item] => Array( [0] => Array( [title] => title1 ) [1] => Array( [title] => title2 ) ) )
-
The UrlMatcher urldecodes the route parameters only once, they were decoded twice before. Note that the
urldecode()calls have been changed for a singlerawurldecode()in order to support+for input paths. -
Two new parameters have been added to the DIC:
router.request_context.hostandrouter.request_context.scheme. You can customize them for your functional tests or for generating urls with the right host and scheme when your are in the cli context.
- session options: lifetime, path, domain, secure, httponly were deprecated. Prefixed versions should now be used instead: cookie_lifetime, cookie_path, cookie_domain, cookie_secure, cookie_httponly
Before:
framework:
session:
lifetime: 3600
path: \
domain: example.com
secure: true
httponly: trueAfter:
framework:
session:
cookie_lifetime: 3600
cookie_path: \
cookie_domain: example.com
cookie_secure: true
cookie_httponly: trueAdded handler_id, defaults to session.handler.native_file.
framework:
session:
storage_id: session.storage.native
handler_id: session.handler.native_fileTo use mock session storage use the following. handler_id is irrelevant in this context.
framework:
session:
storage_id: session.storage.mock_file- You must clear old profiles after upgrading to 2.1. If you are using a database then you will need to remove the table.