Symfony 2: Обновление до 2.3
Обновление Symfony до 2.3 версии.
Обновление Symfony 2.0 до 2.1
- The merging strategy for assets_base_urls and base_urls has changed;
- Переместили DoctrineBundle из Symfony репозитория в Doctrine репозиторий. Нужно изменить namespace в app/AppKernel.php:
new Symfony\Bundle\DoctrineBundle\DoctrineBundle()
// заменить на:
new Doctrine\Bundle\DoctrineBundle\DoctrineBundle() - Менеджер локали перенесен из Session класса в Request класс:
# было
framework:
session:
default_locale: fr
# теперь
framework:
default_locale: fr
- Получение локали в Twig и PHP шаблонах:
{{ app.request.session.locale }} >> {{ app.request.locale }} или $view['request']->getLocale()
- Безопасность. Перемещен метод
equals()
(подробнее):Symfony\Component\Security\Core\User\UserInterface::equals()
// в
Symfony\Component\Security\Core\User\EquatableInterface::isEqualTo()
Можно просто переименовать вашequals(),
реализованный вUser
классе, вisEqualTo()
и реализоватьEquatableInterface
. - Изменен способ регистрации кастомных фабрик для настройки
firewall
. Теперь они регистрируются вbundle
классе (подробнее) - Firewall listener теперь регистрируется после Router listener. Теперь все защищенные URL должны иметь соответствующие роуты в настройке маршрутов. Также, при использовании кастомной 404 страницы убедитесь, что вы не используете функции, связанные с безопасностью, как то
is_granted
. - Изменена настройка провайдеров пользователей:
# Было
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] }
# Сейчас
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
теперь принимает null;UserPassword
перемещен изSecurity Bundle
вSecurity Component
:// до
use Symfony\Bundle\SecurityBundle\Validator\Constraint\UserPassword;
use Symfony\Bundle\SecurityBundle\Validator\Constraint as SecurityAssert;
// после
use Symfony\Component\Security\Core\Validator\Constraint\UserPassword;
use Symfony\Component\Security\Core\Validator\Constraint as SecurityAssert;- Формы... Метод buildViewBottomUp() переименован в finishView();
- Методы buildView() и finishView() принимают
$options
третим аргументом, а все "строительные" методы этих типов принимают FormBuilderInterface вместо FormBuilder. At last, all methods in these types now receive instances of where they received instances of FormBuilder before.# Было
use Symfony\Component\Form\FormBuilder;
public function buildForm(FormBuilder $builder, array $options)
# Теперь
use Symfony\Component\Form\FormBuilderInterface;
public function buildForm(FormBuilderInterface $builder, array $options) - Метод createBuilder был удален из FormTypeInterface для повышения производительности. It is now not possible anymore to use custom implementations of FormBuilderInterface for specific form types. Возможно, вы захотите реализовать свой собственный
ResolvedFormTypeInterface
. - Кастомные типы полей. Вместо
FieldType
нужно наследоватьFormType
, а опцию compaund нужно установить в false, если ваше поле не содержит дочерние поля.// до
public function getParent(array $options)
{
return 'field';
}
// теперь
public function getParent(/* !ни какие опции не передаются! */)
{
return 'form';
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'compound' => false,
));
} - Опция
data_class
теперь должна быть установлена, если форма мапится на объект. Если установитьnull
, тогда форма будет ожидать объект типа ArrayAccess (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). - The mapping of property paths to arrays has changed. Previously, a property path "street" mapped to both a field $street of a class (or its accessors getStreet() and setStreet()) 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.
If address is an object in this case, the code given in "Before" works without changes.// раньше
$builder->add('name', 'text', array(
'property_path' => 'address.street',
));
// сейчас
$builder->add('name', 'text', array(
'property_path' => 'address[street]',
)); - Формы и поля в Symfony 2.3 должны именоваться с буквы, цифры или подчеркивания и содержать только буквы, цифры, подчеркивания, тире и двоеточия.
- В prototype-шаблоне "заглушка" в части имени и id теперь именуется, как
__name__
вместо;$$name$$
- Опция
read_only
рендеритreadonly="readonly"
, для отключения choise поля нужно использоватьdisabled
; - Вложенные формы не валлидируются автоматически, необходимо явно задать
Valid
ограничения в модели. Если вы не хотите использоватьValid
ограничения или из родительской формы нет ссылки на дочернюю - можно включить валидацию вложенных форм опциейcascade_validation = true
; - FormType и FieldType были объединены и требуют адаптации вашей темы.
Блокпереименован вfield_widget
form_widget_simple
.
Все прочиеfield_* (field_row, field_error, etc)
блоки переименованы вform_*
.
Объединены блокиgeneric_labelиform_label
в один -form_label
.
Блокпереименован вwidget_choice_options
choice_widget_options
.
Использовать так:{% block url_widget %}
{% spaceless %}
{% set type = type|default('url') %}
{{ block('form_widget_simple') }}
{% endspaceless %}
{% endblock url_widget %}Если вы использовали разные темы дляfield_*
иform_*
блоков, вы можете объединить их вform_*
блок и внутри него добавить{% if compound %}
условие. Если тип поля - форма,compaund = true
. - Новый формат генерации имен для name и id атрибутов полей. Теперь значение (value) находится в атрибуте value, а к вместо него к этим атрибутам добавляется индекс (целое число).
- Для получения выбранного значения в шаблоне choise поля теперь используется фильтр selectedchoice. Как и
_form_is_choice_groupиспользуется для ... (Similarly, the _form_is_choice_group method used to check if a choice is grouped has been removed and can be checked with the iterable test):{% 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 %}
- Создание дефолтных
label
вынесли на уровень шаблона, теперь нужно самому описать что показывать пользователю, если метка отсутствует:{% block form_label %}
{% if label is empty %}
{% set label = name|humanize %}
{% endif %}
{# ... #}
{% endblock %} - Удалены кастомные темы для каждой строки коллекции для повышения производительности. Теперь нужно использовать ключевое слово entry в имени строк коллекции, которое заменяет индекс строки:
{% block _author_tags_entry_label %}
{# ... #}
{% endblock %} - Метод
хелпера PHP Templating переименован вrenderBlock()
block()
. Первым аргументом ожидается объект классаFormView
:<?php echo $view['form']->block($form, 'widget_attributes') ?>
- Изменен порядок аргументов в методах
createNamed
иcreateNamedBuilder
вFormFactoryInterface
:$form = $factory->createNamed('firstName', 'text');
- Много изменений в реализации
ChoiceList
., в результате заменилиArrayChoiceList
. Если вы расширяли эти классы кастомными - вы должны расширитьSimpleChoiceList
и передать опции выбора в parent конструктор (подробнее):
Если есть необходимость ленивой подгрузки опций, т.е. как только они доступны впервые - вы можете расширитьclass MyChoiceList extends SimpleChoiceList
{
public function __construct()
{
// load choices
parent::__construct($choices);
}
}LazyChoiceList
вместо переопределенияloadChoiceList()
:
Удаленыclass MyChoiceList extends LazyChoiceList
{
protected function loadChoiceList()
{
// load choices
return new SimpleChoiceList($choices);
}
}PaddedChoiceList,MonthChoiceListиTimezoneChoiceList. Их функции объединены сDateType
,TimeType
иTimezoneType
.
Был адаптирован EntityChoiceList. МетодыgetEntities(),getEntitiesByKeys(),getIdentifier()иgetIdentifierValues()были удалены или скрыты (сделаны приватными). ВместоgetEntities*()
используйтеgetChoices()
иgetChoicesByValues()
. - Для form_label функции атрибуты теперь устанавливаются с ключем label_attr:
{{ form_label(form.name, 'Your Name', { 'label_attr': {'class': 'foo'} }) }}
EntitiesToArrayTransformer
заменили наCollectionToArrayTransformer
в сочетании сEntityChoiceList
;EntityToIdTransformer
удален и больше не требуется- Переименованы трансформеры в соответствии с
ChoiceListInterface
:
ArrayToBooleanChoicesTransformer >> ChoicesToBooleanArrayTransformer
ScalarToBooleanChoicesTransformer >> ChoiceToBooleanArrayTransformer
ArrayToChoicesTransformer >> ChoicesToValuesTransformer
ScalarToChoiceTransformer >> ChoiceToValueTransformer - FormUtil::toArrayKey() и FormUtil::toArrayKeys() были объединены внутри ChoiceList и не имеют аналогов;
- Методы add(), remove(), setParent(), bind() and setData() бросают исключение если форма уже связана (form is already bound);
- Если вы использовали FormEvents::PRE_BIND or FormEvents::BIND для связывания форм (on bound forms) - вы должны перести вашу логику в слушатели событий (event listener);
- Методы
иgetDefaultOptions()
(в Symfony 2.3) интерфейсовgetAllowedOptionValues()FormTypeInterface
иFormTypeExtensionInterface
заменили на одинsetDefaultOptions()
:
Используйте замыкания чтобы установить зависимые параметры:public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'gender' => 'male',
));
$resolver->setAllowedValues(array(
'gender' => array('male', 'female'),
));
}
Второй аргумент $value содержит текущие дефолтные значения и не должен передаваться без необходимости.public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'empty_data' => function (Options $options, $value) {
return $options['multiple'] ? array() : $value;
}
));
} - Переименованы методы в
FormBuilder
'е:
>>prependClientTransformer()addViewTransformer()
, передатьtrue
вторым аргументом
appendClientTransformer() >> addViewTransformer()
getClientTransformers() >> getViewTransformers()
resetClientTransformers() >> resetViewTransformers()
prependNormTransformer() >> addModelTransformer()
appendNormTransformer() >> addModelTransformer(), передатьtrue
вторым аргументом
getNormTransformers() >> getModelTransformers()
resetNormTransformers() >> resetModelTransformers() - Переименованы события:
FormEvents::SET_DATA
>>FormEvents::PRE_SET_DATA
FormEvents::BIND_CLIENT_DATA >> FormEvents::PRE_BIND
FormEvents::BIND_NORM_DATA >> FormEvents::BIND
Также классы событийDataEventиFilterDataEventзаменили наFormEvent
:$builder->addListener(FormEvents::PRE_BIND, function (FormEvent $event) {
// ...
}); - Удален FormValidatorInterface. Для реализации кастомной валидации используйте event listeners и слушайте FormEvents::POST_BIND событие (или другое *BIND событие). Если вы использовали класс CallbackValidator - передайте его непосредственно в addEventListener.
- Метод
guessMinLength()дляFormTypeGuesserInterface
заменили наguessPattern()
. Этот метод может возвращать регулярку, которая вставляется в HTML5 атрибутpattern
:public function guessPattern($class, $property)
{
if (/* condition */) {
return new ValueGuess('.{'.$minLength.',}', Guess::LOW_CONFIDENCE);
}
} - В Symfony 2.3 больше не поддерживается значение
для опцииfalse
property_path
. Используйте mapped, для установки мапинга поля на parent данные:$builder->add('termsAccepted', 'checkbox', array(
// 'property_path' => false, << deprecated!
'mapped' => false,
)); - Удалены или заменеы следующие методы:
К другим методам можно получить доступ через FormConfigInterface объект.getTypes() getErrorBubbling() >> $form->getConfig()->getErrorBubbling(); getNormTransformers() getClientTransformers() getAttribute() hasAttribute() getClientData() >> getViewData() getChildren() >> all() hasChildren() >> count() bindRequest() >> bind()
- Опция
переименована наvalidation_constraint
constraints
, которой вы можете задать один или несколько ограничений (условий) для формы.
Ограничения будут применены только если они принадлежат валидируемой группе (в данном случаеCustom
):$builder->add('name', 'text', array(
'constraints' => new NotBlank() // можете передать массив ограничений
// or
'constraints' => array(
new NotBlank(array('groups' => 'Custom')),
new MinLength(3),
)
)); - Переименованы опции
data_timezone
>>model_timezone
иuser_timezone>>view_timezone
из DateType, DateTimeType и TimeType:$builder->add('scheduledFor', 'date', array(
'model_timezone' => 'UTC',
'view_timezone' => 'America/New_York',
)); - Методы addType, hasType и getType фабрики формы (
FormFactory
) теперь нужно вызывать изFormRegistry
(form.registry
):# до
$this->get('form.factory')->addType(new MyFormType());
# в Symfony 2.3
$registry = $this->get('form.registry');
$registry->addType($registry->resolveType(new MyFormType())); - Удалены следующие методы из FormView класса: set(), has(), get(), all(), getVars(), addChild(), getChild(), getChildren(), removeChild(), hasChild(), hasChildren(), getParent(), hasParent(), setParent(). Вместо этого, вы получаете доступ к публичным свойствам
vars
,children
иparent
.# ранее
$view->set('help', 'A text longer than six characters');
$view->set('error_class', 'max_length_error');
# сейчас
$view->vars = array_replace($view->vars, array(
'help' => 'A text longer than six characters',
'error_class' => 'max_length_error',
));$view->hasChildren() >> count($view->children)
$view->get('error_class') >> $view->vars['error_class']
- продолжение... https://github.com/symfony/symfony/blob/2.3/UPGRADE-2.1.md#validator