В этой статье я хотел бы рассказать о некоторых нюансах, через которые пришлось пройти для миграции проекта с устаревшей Symfony 2.0 до актуальной Symfony 2.6.
В каждом проекте Symfony есть свои зависимости (бандлы). В версии 2.0 зависимости указывались в файле deps и подтягивались командой:
Сейчас для этих целей актуально использовать Composer.
Скачиваем Composer в корень репозитория:
Затем мы создаем в корне проекта файл composer.json с следующим содержанием:
github.com/symfony/symfony/blob/2.6/composer.json
И выполням команду:
После этого к нашему проекту подтянется Symfony 2.6 со всеми нужными для него зависимостями и создастся файл composer.lock, в который запишутся актуальные версии скачанных зависимостей.
Все, что нам осталось — это добавить в файл composer.json нужные нам зависимости. Это можно сделать вручную, редактируя файл:
Либо с помощью команды:
Теперь у нас есть все необходимы бандлы и мы можем удалить файлы deps и deps.lock, но для корректной работы фреймворка нам так же следует обновить файлы web/app.php и web/app_dev.php:
Для версии Symfony 2.0 параметры подгружались из файла app/config/parameters.ini. Все что нам нужно — это переименовать его в app/config/parameters.yml и привести к виду yml файла:
Before:
After:
Затем в app/config/config.yml пропишем путь для нашего файла:
Параметры изменены и подключены.
С версии 2.0 до 2.6 произошло довольно много изменений, я бы хотел рассказать только о некоторых из них.
Некоторые функции теперь вызывают исключения, если их использовать на уже отправленной форме:
Их можно вызывать из listener в formBuilder непосредственно перед отправкой формы, либо немного изменить логику работы вашей формы. Но в качестве временной меры можно воспользоваться таким вот кодом:
После того как мы заново создали форму и передали в нее все параметры из старой формы, мы можем использовать на ней все те функции, что нельзя было использовать на уже отправленной форме.
Вместо использования в FormBulder более не существующего класса CallbackValidation мы просто используем EventListener, после того, как форма уже отправлена т.е. POST_SUBMIT.
Before:
After:
При создании своей опции в поле формы MyBundle\Forms\ExtensionExtensionForm.php; необходимо указывать, для какого типа полей будут добавляются эти опции:
Если мы хотим добавить их для всех типов полей, необходимо указать:
github.com/symfony/symfony/blob/2.7/UPGRADE-2.1.md
github.com/symfony/symfony/blob/2.7/UPGRADE-2.2.md
github.com/symfony/symfony/blob/2.7/UPGRADE-2.3.md
github.com/symfony/symfony/blob/2.7/UPGRADE-2.4.md
github.com/symfony/symfony/blob/2.7/UPGRADE-2.5.md
github.com/symfony/symfony/blob/2.7/UPGRADE-2.6.md
Официальная документация Symfony: symfony.com/doc/current/cookbook/index.html
Менеджер зависимостей
В каждом проекте Symfony есть свои зависимости (бандлы). В версии 2.0 зависимости указывались в файле deps и подтягивались командой:
php bin/vendors install
Сейчас для этих целей актуально использовать Composer.
Скачиваем Composer в корень репозитория:
php -r "readfile('https://getcomposer.org/installer');" | php
Затем мы создаем в корне проекта файл composer.json с следующим содержанием:
github.com/symfony/symfony/blob/2.6/composer.json
И выполням команду:
php composer.phar update
После этого к нашему проекту подтянется Symfony 2.6 со всеми нужными для него зависимостями и создастся файл composer.lock, в который запишутся актуальные версии скачанных зависимостей.
Все, что нам осталось — это добавить в файл composer.json нужные нам зависимости. Это можно сделать вручную, редактируя файл:
"require": { "{название зависимости}":"{версия зависимости}" },
Либо с помощью команды:
php composer.phar require {название зависимости}:{версия зависимости}
Теперь у нас есть все необходимы бандлы и мы можем удалить файлы deps и deps.lock, но для корректной работы фреймворка нам так же следует обновить файлы web/app.php и web/app_dev.php:
app.php
<?php use Symfony\Component\ClassLoader\ApcClassLoader; use Symfony\Component\HttpFoundation\Request; $loader = require_once __DIR__.'/../app/bootstrap.php.cache'; // Enable APC for autoloading to improve performance. // You should change the ApcClassLoader first argument to a unique prefix // in order to prevent cache key conflicts with other applications // also using APC. /* $apcLoader = new ApcClassLoader(sha1(__FILE__), $loader); $loader->unregister(); $apcLoader->register(true); */ require_once __DIR__.'/../app/AppKernel.php'; //require_once __DIR__.'/../app/AppCache.php'; $kernel = new AppKernel('prod', false); $kernel->loadClassCache(); //$kernel = new AppCache($kernel); // When using the HttpCache, you need to call the method in your front controller instead of relying on the configuration parameter //Request::enableHttpMethodParameterOverride(); $request = Request::createFromGlobals(); $response = $kernel->handle($request); $response->send(); $kernel->terminate($request, $response);
app_dev.php
<?php use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Debug\Debug; // If you don't want to setup permissions the proper way, just uncomment the following PHP line // read http://symfony.com/doc/current/book/installation.html#configuration-and-setup for more information //umask(0000); // This check prevents access to debug front controllers that are deployed by accident to production servers. // Feel free to remove this, extend it, or make something more sophisticated. if (isset($_SERVER['HTTP_CLIENT_IP']) || isset($_SERVER['HTTP_X_FORWARDED_FOR']) || !(in_array(@$_SERVER['REMOTE_ADDR'], array('127.0.0.1', 'fe80::1', '::1')) || php_sapi_name() === 'cli-server') ) { header('HTTP/1.0 403 Forbidden'); exit('You are not allowed to access this file. Check '.basename(__FILE__).' for more information.'); } $loader = require_once __DIR__.'/../app/bootstrap.php.cache'; Debug::enable(); require_once __DIR__.'/../app/AppKernel.php'; $kernel = new AppKernel('dev', true); $kernel->loadClassCache(); $request = Request::createFromGlobals(); $response = $kernel->handle($request); $response->send(); $kernel->terminate($request, $response);
Параметры
Для версии Symfony 2.0 параметры подгружались из файла app/config/parameters.ini. Все что нам нужно — это переименовать его в app/config/parameters.yml и привести к виду yml файла:
Before:
[parameters] locale = en
After:
parameters: locale: en
Затем в app/config/config.yml пропишем путь для нашего файла:
imports: - { resource: parameters.yml }
Параметры изменены и подключены.
Обратная совместимость функций
С версии 2.0 до 2.6 произошло довольно много изменений, я бы хотел рассказать только о некоторых из них.
Формы:
Некоторые функции теперь вызывают исключения, если их использовать на уже отправленной форме:
add(), remove(), setParent(), bind() and setData()
Их можно вызывать из listener в formBuilder непосредственно перед отправкой формы, либо немного изменить логику работы вашей формы. Но в качестве временной меры можно воспользоваться таким вот кодом:
$formData = $form->getData(); $form = $this->createForm(new YourForm()); $form->setData($formData);
После того как мы заново создали форму и передали в нее все параметры из старой формы, мы можем использовать на ней все те функции, что нельзя было использовать на уже отправленной форме.
Валидация форм:
Вместо использования в FormBulder более не существующего класса CallbackValidation мы просто используем EventListener, после того, как форма уже отправлена т.е. POST_SUBMIT.
Before:
$builder->addValidator(new CallbackValidator(function (FormInterface $form) { $value = $form['date']->getData(); if ($value != null) { $form['date']->addError(new FormError('Введена некорректная дата')); } }));
After:
$builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) { $form = $event->getForm(); $value = $form['date']->getData(); if ($value != null) { $form['date']->addError(new FormError('Введена некорректная дата')); } });
Добавление своей опции в поле формы
При создании своей опции в поле формы MyBundle\Forms\ExtensionExtensionForm.php; необходимо указывать, для какого типа полей будут добавляются эти опции:
public function getExtendedType() { return 'text'; }
Если мы хотим добавить их для всех типов полей, необходимо указать:
public function getExtendedType() { return 'form'; }
Полный перечень изменений
github.com/symfony/symfony/blob/2.7/UPGRADE-2.1.md
github.com/symfony/symfony/blob/2.7/UPGRADE-2.2.md
github.com/symfony/symfony/blob/2.7/UPGRADE-2.3.md
github.com/symfony/symfony/blob/2.7/UPGRADE-2.4.md
github.com/symfony/symfony/blob/2.7/UPGRADE-2.5.md
github.com/symfony/symfony/blob/2.7/UPGRADE-2.6.md
Официальная документация Symfony: symfony.com/doc/current/cookbook/index.html
