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.1.md

551 lines
16 KiB
Markdown
Raw Normal View History

UPGRADE FROM 2.0 to 2.1
2011-10-08 17:29:31 +01:00
=======================
### General
* The merging strategy for `assets_base_urls` and `base_urls` has changed.
2011-10-08 17:29:31 +01:00
Unlike most configuration blocks, successive values for `assets_base_urls`
will 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.yml` imports `config_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.
2011-10-08 17:29:31 +01:00
### HttpFoundation
2012-02-23 04:10:06 +00:00
* Locale management was moved from the Session class to the Request class.
##### Configuring the default locale
2012-01-17 09:53:31 +00:00
Before:
```
framework:
session:
default_locale: fr
```
2012-01-17 09:53:31 +00:00
After:
```
framework:
default_locale: fr
```
* The methods `getPathInfo()`, `getBaseUrl()` and `getBasePath()` of
a `Request` now all return a raw value (vs a urldecoded value before). Any call
to one of these methods must be checked and wrapped in a `rawurldecode()` if
needed.
##### Retrieving the locale from a Twig template
Before: `{{ app.request.session.locale }}` or `{{ app.session.locale }}`
2012-02-02 11:36:28 +00:00
2012-01-17 09:53:31 +00:00
After: `{{ app.request.locale }}`
##### Retrieving the locale from a PHP template
Before: `$view['session']->getLocale()`
2012-02-02 11:36:28 +00:00
2012-01-17 09:53:31 +00:00
After: `$view['request']->getLocale()`
##### Retrieving the locale from PHP code
Before: `$session->getLocale()`
2012-02-02 11:36:28 +00:00
2012-01-17 09:53:31 +00:00
After: `$request->getLocale()`
### Security
* `Symfony\Component\Security\Core\User\UserInterface::equals()` has moved to
`Symfony\Component\Security\Core\User\EquatableInterface::isEqualTo()`.
You must rename the `equals()` method in your implementation of the `User`
class to `isEqualTo()` and implement `EquatableInterface`. 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 implement `EquatableInterface` and remove your
comparison method.
2012-01-17 09:53:31 +00:00
Before:
```
class User implements UserInterface
{
// ...
public function equals(UserInterface $user) { /* ... */ }
// ...
}
```
2012-01-17 09:53:31 +00:00
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 you need to remove the 'factories'
keys in your security configuration.
* 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.
* The user provider configuration has been refactored. The configuration
for the chain provider and the memory provider has been changed:
Before:
``` yaml
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:
``` yaml
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::setParentAcl` now accepts `null`, review any
implementations of this interface to reflect this change.
### Form and Validator
2012-01-17 09:53:31 +00:00
* Child forms are no longer automatically validated. That means that you must
explicitly set the `Valid` constraint in your model if you want to validate
associated objects.
2012-01-17 09:53:31 +00:00
2012-02-11 11:44:56 +00:00
If you don't want to set the `Valid` constraint, 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` form option to `true`
on the parent form.
* Changed implementation of choice lists
ArrayChoiceList was replaced. If you have custom classes that extend this
class, you must now extend SimpleChoiceList.
2012-01-30 10:10:25 +00:00
Before:
```
class MyChoiceList extends ArrayChoiceList
{
protected function load()
2012-01-30 10:10:25 +00:00
{
parent::load();
// load choices
$this->choices = $choices;
2012-01-30 10:10:25 +00:00
}
}
```
2012-01-30 10:10:25 +00:00
After:
```
class MyChoiceList extends SimpleChoiceList
{
public function __construct()
2012-01-30 10:10:25 +00:00
{
// load choices
parent::__construct($choices);
2012-01-30 10:10:25 +00:00
}
}
```
2012-01-30 10:10:25 +00:00
If you need to load the choices lazily -- that is, as soon as they are
accessed for the first time -- you can extend LazyChoiceList instead.
2012-01-30 10:10:25 +00:00
```
class MyChoiceList extends LazyChoiceList
{
protected function loadChoiceList()
2012-01-30 10:10:25 +00:00
{
// load choices
return new SimpleChoiceList($choices);
2012-01-30 10:10:25 +00:00
}
}
```
PaddedChoiceList, MonthChoiceList and TimezoneChoiceList were removed.
Their functionality was merged into DateType, TimeType and TimezoneType.
EntityChoiceList was adapted. The methods `getEntities()`,
`getEntitiesByKeys()`, `getIdentifier()` and `getIdentifierValues()` were
removed or made private. Instead of the first two, you can now use
`getChoices()` and `getChoicesByValues()`. For the latter two, no
replacement exists.
2012-04-10 14:32:55 +01:00
* The strategy for generating the `id` and `name` HTML attributes for
checkboxes and radio buttons in a choice field has changed.
2012-02-02 11:36:28 +00:00
Instead of appending the choice value, a generated integer is now appended
2012-04-10 14:32:55 +01:00
by default. Take care if your JavaScript relies on that.
* In the choice field type's template, the structure of the `choices` variable
has changed.
2012-01-24 00:23:01 +00:00
The `choices` variable now contains ChoiceView objects with two getters,
`getValue()` and `getLabel()`, to access the choice data. The indices of the
array are controlled by the choice field's `index_generation` option.
2012-01-24 00:23:01 +00:00
Before:
```
{% for choice, label in choices %}
<option value="{{ choice }}"{% if _form_is_choice_selected(form, choice) %} selected="selected"{% endif %}>
{{ label }}
</option>
{% endfor %}
```
2012-01-24 00:23:01 +00:00
After:
```
{% for choice in choices %}
<option value="{{ choice.value }}"{% if _form_is_choice_selected(form, choice) %} selected="selected"{% endif %}>
{{ choice.label }}
</option>
{% endfor %}
```
* In the collection type's template, the default name of the prototype field
has changed from `$$name$$` to `__name__`.
For custom names, dollar signs are no longer prepended and appended. You are
advised to prepend and append two underscores wherever you specify a value
for the field's `prototype_name` option.
Before:
```
$builder->add('tags', 'collection', array('prototype' => 'proto'));
// results in the name "$$proto$$" in the template
```
After:
```
$builder->add('tags', 'collection', array('prototype' => '__proto__'));
// results in the name "__proto__" in the template
```
* The `read_only` field attribute now renders as `readonly="readonly"`, use
`disabled` instead for `disabled="disabled"`.
* Form and field names must now start with a letter, digit or underscore
and only contain letters, digits, underscores, hyphens and colons
* `EntitiesToArrayTransformer` and `EntityToIdTransformer` have been removed.
The former has been replaced by `CollectionToArrayTransformer` in combination
with `EntityChoiceList`, the latter is not required in the core anymore.
* The following transformers have been renamed:
* `ArrayToBooleanChoicesTransformer` to `ChoicesToBooleanArrayTransformer`
* `ScalarToBooleanChoicesTransformer` to `ChoiceToBooleanArrayTransformer`
* `ArrayToChoicesTransformer` to `ChoicesToValuesTransformer`
* `ScalarToChoiceTransformer` to `ChoiceToValueTransformer`
to be consistent with the naming in `ChoiceListInterface`.
* `FormUtil::toArrayKey()` and `FormUtil::toArrayKeys()` have been removed.
They were merged into ChoiceList and have no public equivalent anymore.
* The methods `setMessage()`, `getMessageTemplate()` and
`getMessageParameters()` in the Constraint class were deprecated.
If you have implemented custom validators, you should use the
`addViolation()` method on the `ExecutionContext` object 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;
merged branch bschussek/issue2615 (PR #3228) Commits ------- 2e4ebe4 [Validator] Renamed methods addViolationAtRelativePath() and getAbsolutePropertyPath() in ExecutionContext 9153f0e [Validator] Deprecated ConstraintValidator methods setMessage(), getMessageTemplate() and getMessageParameters() 0417282 [Validator] Fixed typos a30a679 [Validator] Made ExecutionContext immutable and introduced new class GlobalExecutionContext fe85bbd [Validator] Simplified ExecutionContext::addViolation(), added ExecutionContext::addViolationAt() f77fd41 [Form] Fixed typos 1fc615c Fixed string access by curly brace to bracket a103c28 [Validator] The Collection constraint adds "missing" and "extra" errors to the individual fields now f904a9e [Validator] Fixed: GraphWalker does not add constraint violation if error message is empty 1dd302c [Validator] Fixed ConstraintViolationList::__toString() to not include dots in the output if the root is empty 1678a3d [Validator] Fixed: Validator::validateValue() propagates empty validation root instead of the provided value Discussion ---------- [Validator] Improved "missing" and "extra" errors of Collection constraint Bug fix: yes Feature addition: no Backwards compatibility break: no Symfony2 tests pass: yes Fixes the following tickets: #2615 Todo: - ![Travis Build Status](https://secure.travis-ci.org/bschussek/symfony.png?branch=issue2615) Instead of a single violation Array: The fields "foo", "bar" are missing various violations are now generated. Array[foo]: This field is missing Array[bar]: This field is missing Apart from that, the PR contains various minor fixes to the Validator. --------------------------------------------------------------------------- by bschussek at 2012-02-02T09:14:52Z @fabpot Ready for merge.
2012-02-02 09:16:32 +00:00
}
}
```
* The method `setPropertyPath()` in the ExecutionContext class
was removed.
You should use the `addViolationAtSubPath()` method on the
`ExecutionContext` object 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 options passed to the `getParent()` method of form types no longer
contain default options. They only contain the options passed by the user.
2012-02-11 11:44:56 +00:00
You should check if options exist before attempting to read their value.
2012-02-11 11:44:56 +00:00
Before:
```
public function getParent(array $options)
{
return 'single_text' === $options['widget'] ? 'text' : 'choice';
}
```
2012-02-11 11:44:56 +00:00
After:
```
public function getParent(array $options)
{
return isset($options['widget']) && 'single_text' === $options['widget'] ? 'text' : 'choice';
}
```
* The methods `getDefaultOptions()` and `getAllowedOptionValues()` of form
types no longer receive an option array.
You can specify options that depend on other options using closures instead.
Before:
```
public function getDefaultOptions(array $options)
{
$defaultOptions = array();
if ($options['multiple']) {
$defaultOptions['empty_data'] = array();
}
return $defaultOptions;
}
```
After:
```
public function getDefaultOptions()
{
2012-04-05 15:12:22 +01:00
return array(
'empty_data' => function (Options $options, $previousValue) {
return $options['multiple'] ? array() : $previousValue;
}
);
}
```
The second argument `$previousValue` does not have to be specified if not
needed.
* The `add()`, `remove()`, `setParent()`, `bind()` and `setData()` 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 one of the following events:
`FormEvents::PRE_BIND`, `FormEvents::BIND_CLIENT_DATA` or
`FormEvents::BIND_NORM_DATA`.
### Session
* Flash messages now return an array based on their type. The old method is
still available but is now deprecated.
##### Retrieving the flash messages from a Twig template
Before:
```
2012-03-23 17:01:12 +00:00
{% if app.session.hasFlash('notice') %}
<div class="flash-notice">
2012-03-23 17:01:12 +00:00
{{ app.session.getFlash('notice') }}
</div>
{% endif %}
```
After:
```
2012-02-11 06:41:34 +00:00
{% for flashMessage in app.session.flashbag.get('notice') %}
<div class="flash-notice">
2012-02-11 06:41:34 +00:00
{{ flashMessage }}
</div>
2012-02-11 06:41:34 +00:00
{% endfor %}
```
2012-03-23 17:01:12 +00:00
You can process all flash messages in a single loop with:
```
2012-02-11 06:41:34 +00:00
{% for type, flashMessages in app.session.flashbag.all() %}
2012-03-25 22:27:20 +01:00
{% for flashMessage in flashMessages %}
2012-02-11 06:41:34 +00:00
<div class="flash-{{ type }}">
{{ flashMessage }}
</div>
{% endfor %}
2012-02-25 15:44:52 +00:00
{% endfor %}
```
2012-03-06 19:41:09 +00:00
* Session handler drivers should implement `\SessionHandlerInterface` or extend from
2012-03-23 07:16:11 +00:00
`Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeHandlerInterface` base class and renamed
2012-03-06 19:41:09 +00:00
to `Handler\FooSessionHandler`. E.g. `PdoSessionStorage` becomes `Handler\PdoSessionHandler`.
2012-03-06 19:41:09 +00:00
* Refactor code using `$session->*flash*()` methods to use `$session->getFlashBag()->*()`.
### Serializer
* The key names craeted by the `GetSetMethodNormalizer` have changed from
from all lowercased to camelCased (e.g. `mypropertyvalue` to `myPropertyValue`).
* The `item` element is now converted to an array when deserializing XML.
``` 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
)
)
)
### Routing
* The UrlMatcher urldecodes the route parameters only once, they were
decoded twice before. Note that the `urldecode()` calls have been changed for a
single `rawurldecode()` in order to support `+` for input paths.
### FrameworkBundle
* 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: true
```
After:
```
framework:
session:
cookie_lifetime: 3600
cookie_path: \
cookie_domain: example.com
cookie_secure: true
cookie_httponly: true
```
2012-03-06 19:41:09 +00:00
Added `handler_id`, defaults to `session.handler.native_file`.
```
framework:
session:
storage_id: session.storage.native
handler_id: session.handler.native_file
```
To use mock session storage use the following. `handler_id` is irrelevant in this context.
```
framework:
session:
storage_id: session.storage.mock_file
```
### WebProfilerBundle
* You must clear old profiles after upgrading to 2.1. If you are using a
database then you will need to remove the table.
2012-03-06 19:41:09 +00:00