Выпустили Symfony 7, в этой версии представлено множество критических изменений. Я покажу, как я обновляюсь до 7 версии.
Резервное копирование существующего кода
Во-первых, давайте создадим тег GIT для существующего кода и создадим резервную копию проекта.
git tag v6.x
git push origin v6.x
Создайте новую ветку для подготовки работ по обновлению.
git checkout -b v7
Обновите пакеты Symfony до v7
Откройте composer.json файл, измените версию всех пакетов Symfony на 7.0.*.
{
"name": "hantsy/symfony-rest-sample",
"description": "Restful APIs examples built with Symfony 7 and PHP 8",
"authors": [
{
"name": "Pavel Martynenko",
"email": "info@topsite-web.ru"
}
],
"type": "project",
"license": "GPL-3.0-or-later",
"minimum-stability": "stable",
"prefer-stable": true,
"require": {
"php": ">=8.2",
"ext-ctype": "*",
"ext-iconv": "*",
"composer/package-versions-deprecated": "^1.11.99.4",
"doctrine/annotations": "^2.0",
"doctrine/doctrine-bundle": "^2.4",
"doctrine/doctrine-migrations-bundle": "^3.1",
"doctrine/orm": "^2.9",
"phpdocumentor/reflection-docblock": "^5.2",
"symfony/asset": "7.0.*",
"symfony/console": "7.0.*",
"symfony/dotenv": "7.0.*",
"symfony/expression-language": "7.0.*",
"symfony/flex": "^2.0.1",
"symfony/framework-bundle": "7.0.*",
"symfony/monolog-bundle": "^3.7",
"symfony/property-access": "7.0.*",
"symfony/property-info": "7.0.*",
"symfony/runtime": "7.0.*",
"symfony/serializer": "7.0.*",
"symfony/uid": "7.0.*",
"symfony/validator": "7.0.*",
"symfony/yaml": "7.0.*"
},
"config": {
"optimize-autoloader": true,
"preferred-install": {
"*": "dist"
},
"allow-plugins": true,
"sort-packages": true
},
"autoload": {
"psr-4": {
"App\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"App\\Tests\\": "tests/"
}
},
"replace": {
"symfony/polyfill-ctype": "*",
"symfony/polyfill-iconv": "*",
"symfony/polyfill-php72": "*"
},
"scripts": {
"auto-scripts": {
"cache:clear": "symfony-cmd",
"assets:install %PUBLIC_DIR%": "symfony-cmd"
},
"post-install-cmd": [
"@auto-scripts"
],
"post-update-cmd": [
"@auto-scripts"
],
"test": "php bin/phpunit"
},
"conflict": {
"symfony/symfony": "*"
},
"extra": {
"symfony": {
"allow-contrib": false,
"require": "7.0.*"
}
},
"require-dev": {
"dama/doctrine-test-bundle": "^8.0",
"doctrine/doctrine-fixtures-bundle": "^3.4",
"phpunit/phpunit": "^9.5",
"symfony/browser-kit": "7.0.*",
"symfony/css-selector": "7.0.*",
"symfony/maker-bundle": "^1.34",
"symfony/phpunit-bridge": "7.0.*"
}
}
Удалим sensio/framework-extra-bundle и nelmio/cors-bundle из списка пакетов из-за совместимости с новой версией v7.
- Первый вариант устарел в версии 7 и не рекомендуется в новых проектах. Мы будем использовать новый API для их замены.
- Последний на данный момент не выпускает версию, совместимую с Symfony v7.
Удалите composer.lock, попробуйте запустить composer install команду в терминале, чтобы установить новые пакеты, и повторно запустите встроенные рецепты для этого проекта.
Обновите коды с помощью новых API
Есть несколько классов, которые необходимо согласовать с новыми API в Symfony 7.
Во-первых, мы использовали ArgumentResolverin sensio/framework-extra-bundle для преобразования параметров в формат Uuid. В Symfony 7 это ValueResolver замена. Более подробную информацию смотрите в разделе Расширение разрешения аргументов действия.
И есть встроенный UidValueResolver, который можно использовать для преобразования параметра в Uuidv4, поэтому мы можем отказаться от нашего специального конвертера Uuid и переключиться на использование официального.
Просто удалите существующий src/ParamConverter/UuidParamConverter.
Далее давайте обновим BodyValueResolver и QueryParamValueResolver. В седьмой версии оригинал ArgumentValueResolverInterface убран, есть замена ValueResolverInterface, похожая на старую, но способа переопределить ArgumentValueResolverInterface нет.
Мы немного корректируем существующий код, чтобы он работал без проблем.
class QueryParamValueResolver implements ValueResolverInterface, LoggerAwareInterface
{
public function __construct()
{
}
private LoggerInterface $logger;
/**
* @inheritDoc
*/
public function resolve(Request $request, ArgumentMetadata $argument): iterable
{
if (!$this->supports($request, $argument)) return [];
...
}
Мы повторно используем supports метод, чтобы определить, пропустить ли выполнение разрешения аргумента. Аналогично настраиваем, BodyValueResolver как положено.
При запуске composer install, мы получаем следующую ошибку.
!! Symfony\Component\ErrorHandler\Error\FatalError {#307
!! #message: "Compile Error: Declaration of App\Annotation\Delete::getMethods() must be compatible with Symfony\Component\Routing\Attribute\Route::getMethods(): array"
!! #code: 0
!! #file: "D:\hantsylabs\symfony5-sample\src\Annotation\Delete.php"
!! #line: 11
!! -error: array:4 [
!! "type" => 64
!! "message" => "Declaration of App\Annotation\Delete::getMethods() must be compatible with Symfony\Component\Routing\Attribute\Route::getMethods(): array"
!! "file" => "D:\hantsylabs\symfony5-sample\src\Annotation\Delete.php"
!! "line" => 11
!! ]
!! }
!! PHP Fatal error: Declaration of App\Annotation\Delete::getMethods() must be compatible with Symfony\Component\Routing\Attribute\Route::getMethods(): array in D:\hantsylabs\symfony5-sample\src\Annotation\Delete.php on line 11
В Symfony 7 все методы и свойства классов требуют объявления типа.
Symfony предоставляет простой скрипт для обновления существующего кода и автоматического применения объявления типа.
vendor/bin/patch-type-declarations
Дополнительную информацию об объявлении типа смотрите в разделе Объявления типов Symfony 7.0.
Повторите запуск composer install, мы получим новую ошибку, подобную следующей.
!! In Loader.php line 63:
!!
!! Cannot load resource "../../src/Controller/". Make sure there is a loader
!! supporting the "annotation" type.
Нам следует использовать новую конфигурацию атрибутов, чтобы заменить устаревшую конфигурацию аннотаций для загрузки контроллеров.
- Удалить config/routes/annotations.yaml.
- Создайте новый файл config/routes/attributes.yaml, заполните следующее содержимое.
controllers:
resource:
path: ../../src/Controller/
namespace: App\Controller
type: attribute
kernel:
resource: App\Kernel
type: attribute
Дополнительную информацию о маршруте см. в разделе «Создание маршрутов как атрибутов».
Теперь composer install команда должна быть выполнена успешно.
При запуске тестов отображается несколько устаревших предупреждений.
Get, Post, Put, Delete которые мы создали в качестве примеров демонстрации атрибутов, теперь выдают информацию о предупреждении, например, что маршрут может быть окончательным в будущем. Таким образом, это означает, что в следующей версии эти пользовательские атрибуты работать не будут.
- Удалите всю src\Annotations папку.
- Откройте файл PostController и используйте вместо него исходный Route атрибут.
Обратите внимание — если вы используете Route из Symfony\Component\Routing\Annotation\Route, измените его на новый Symfony\Component\Routing\Attribute\Route.
Еще два предупреждения слева взяты из конфигурации Doctrine.
Откройте config/packages/doctrine.yaml, добавьте следующие две строки.
doctrine:
dbal:
url: '%env(resolve:DATABASE_URL)%'
use_savepoints: true // добавить строку
...
orm:
auto_generate_proxy_classes: true
enable_lazy_ghost_objects: true // добавить строку
...
Я не исследовал новые изменения в Doctrine, эти настройки указаны в предупреждении.
Теперь запустите тесты, все тесты должны пройти.
Обновление до PHPUnit 10
Запустите следующую команду, чтобы обновить PHPUnit до версии 10.x.
composer recipes:update symfony/phpunit-bridge
Затем обновите пакеты PHPUnit до ^10.0.
composer install
При запуске тестов в результатах теста содержится некоторая информация об устаревании.
Выполните следующую команду, чтобы перенести конфигурацию в формат, совместимый с PHPUnit 10.
vendor/bin/phpunit --migrate-configuration
Вы обнаружите, что прослушиватель тестов Symfony удален этим скриптом, поскольку listener он не является допустимым элементом в конфигурации PHPUnit 10. Подождем новой замены в дальнейшей версии.
Вручную добавьте source элемент в phpunit.xml.dist.
<source>
<include>
<directory suffix=".php">src</directory>
</include>
</source>
Теперь запустите тесты еще раз, все тесты должны пройти.
Обновление PHP
Наконец, нам следует обновить версию PHP, удалить PHP 8.1 и добавить PHP 8.3 в качестве среды сборки. PHP 8.1 больше не поддерживается в новой версии Symfony 7.