React Router 6 и Атрибуты PHP 8

Месяц назад вышел PHP 8.1 с новыми возможностями. Атрибуты теперь поддерживают вложенность, которой раньше не было. Это нам мешало перейти на них в 8.0. И не все библиотеки поддерживали атрибуты. Теперь же всё поддерживается и нас ничто не останавливает.

Пришла пора завершить переход на PHP 8.0 и перевести проект с классических аннотаций на новые нативные атрибуты для валидатора и Doctrine ORM. Поговорить, что делать с ними в legacy-проектах. И заодно обновиться на новые компоненты из версии Symfony 6 для бэкенда и подключить новый React Router 6 для фронтенда.

  • 00:00:33 Атрибуты в PHP 8
  • 00:07:03 Обновление фронтенда
  • 00:08:53 Переход на React Router 6
  • 00:13:25 Новые версии Cucumber
  • 00:15:02 Исправление закрытия браузера в E2E
  • 00:16:39 Увеличение таймаутов в E2E
  • 00:17:48 Регулировка числа потоков
  • 00:19:08 Версия Xdebug
  • 00:19:55 Обновление API
  • 00:24:58 Валидатор из Symfony 6
  • 00:26:38 Дополнительный тест на валидацию
  • 00:27:51 Восстановление валидации по аннотациям
  • 00:31:58 Перевод валидатора на атрибуты
  • 00:33:35 Перевод Doctrine ORM на атрибуты
  • 00:39:49 Драйвер для чтения атрибутов
  • 00:42:53 Донастройка CS Fixer
  • 00:43:14 Переход на атрибуты в legacy проекте
  • 00:49:20 Обзор результата
Скрытый контент (код, слайды, ...) для подписчиков. Открыть →
Дмитрий Елисеев
elisdn.ru
Комментарии (32)
Руслан
2021-12-20 12:12

Спасибо!

Ответить
slo_nik
2021-12-20 16:53

Добрый вечер, Дмитрий.

Как всегда на отлично)

Сразу же вопрос.

Есть всё-таки возможность поставить overtrue/phplint к symfony6.0? Если да, то как это можно делать?

Или забить на это и ждать пока обновится сам overtrue/phplint на использование symfony/console v6.0?

Вчера пытался найти посвежее пакет phplint, но пока ничего не попалось.

Ответить
Дмитрий Елисеев
2021-12-21 12:48

Или забить на это и ждать

Или отправить Pull Request и не ждать.

Ответить
slo_nik
2021-12-21 12:53

Понял.

И вот ещё такая проблема.

После обновлений появилась ошибка

Firefox не может установить соединение с сервером ws://localhost:3000/ws.

Пробовал в конфигурации nginx для frontend и gateway задать настройки

proxy_connect_timeout 43200000;
proxy_read_timeout 43200000;
proxy_send_timeout 43200000;

Но это не помогло.

Как ещё можно решить данную проблему?

Ответить
Дмитрий Елисеев
2021-12-21 12:57

Для location /ws {...} в проксировании настроить заголовок Connection.

Ответить
slo_nik
2021-12-21 13:05

То есть, нужно создать для ws отдельный блок в настройках nginx, так же как делали для sockjs-node?

    location /sockjs-node {
      proxy_set_header  Host $host;
      proxy_set_header  Upgrade $http_upgrade;
      proxy_set_header  Connection "Upgrade";
      proxy_pass        http://frontend-one-node:3000;
      proxy_redirect    off;
    }
Ответить
Дмитрий Елисеев
2021-12-21 13:21

Да

Ответить
slo_nik
2021-12-21 13:23

А где поискать, как понять, какое именно обновление вызвало этот сбой?

Ответить
Дмитрий Елисеев
2021-12-21 13:30

В CHANGELOG пакетов, у которых были мажорные изменения.

Ответить
slo_nik
2021-12-21 21:02

Ошибка возникла после обновления react-scripts 4.0.3 -> 5.0.0

На github есть issues

Ответить
slo_nik
2021-12-21 17:49

К сожалению не помогает.

Добавил в frontend/docker/development/nginx/conf.d и в gateway/docker/development/nginx/conf.d, но ошибка всё-равно появляется.

Ответить
slo_nik
2021-12-21 18:03

Ругается на файл

node_modules/webpack-dev-server/client/clients/WebSocketClient.js

строка 13

this.client = new WebSocket(url);

Ответить
Максим (@myks92)
2022-01-03 21:56

11 дней назад уже сделал такой PR. 4 дня назад выпустили версию 4.1 где есть поддержка Symfony 6. Пользуйтесь)

Ответить
Arunas
2021-12-20 18:22

Спасибо.

Ответить
Владимир Перепеченко
2021-12-21 20:28

Благодарю Дмитрий, даже я понял про атрибуты.

Интересно, несовместимость каких текущих пакетов помешала Вам прыгнуть сразу на PHP 8.1 ?

Традиционные вопросы чайника:

Какие папки мы вправе указывать как metadata_dirs для доктрины?

  1. можем ли сразу указать для всего проекта /src ? Или рекурсивно она не ищет? Или ищет но медленно?
  2. должны ли в указанных папках находится только файлы entity или там имеет право быть ещё всякий мусор?
Ответить
Дмитрий Елисеев
2021-12-22 09:04

несовместимость каких текущих пакетов помешала Вам прыгнуть сразу на PHP 8.1

Пару недель назад были мелкие проблемы у PHP-CS-Fixer, которые уже исправили. Сейчас есть deprecations у пакета willdurand/negotiation.

А так в любом проекте можно посмотреть явно мешающие пакеты командой:

docker-compose run --rm api-php-cli composer why-not php 8.1

Для проверки реальной совместимости можно попробовать в локальном Dockerfile и composer.json поменять версию и после пересборки запустить api-check.

Но помимо смены версии желательно и код перевести на новые возможности вроде readonly и Enums. Так что для перехода на PHP 8.1 нужен будет отдельный подробный эпизод.

Ответить
Дмитрий Елисеев
2021-12-22 09:30

Именно. В своём коде это всё находит Psalm, но в коде чужих библиотек могут быть проблемы.

Ответить
Владимир Перепеченко
2021-12-22 09:36

К сожалению, Psalm найдёт только если разработчик сам поставил deprecated в аннотации в докблоке своего кода.

А просто deprecated функции или куски кода в голом PHP он не находит.

Ранее у phpstan был плагин для поиска подобных вещей, но он давно не обновляется, так что сейчас в опенсорсе, наверное, и нет ничего, для поиска deprecated кода.

Ответить
Дмитрий Елисеев
2021-12-22 09:18

Можем ли сразу указать для всего проекта /src? Или рекурсивно она не ищет?

Можем. Рекурсивно ищет.

Или там имеет право быть ещё всякий мусор?

Может быть мусор, как у нас там лежат классы типов и репозиториев.

Ответить
Владимир Перепеченко
2021-12-22 09:31

Благодарю! Тогда в чем фишка это фишки? При каких обстоятельтвах мы вынуждены будем указывать в массиве конфига кучу отдельных папок для Entity вместо просто одной папки?

Ответить
Дмитрий Елисеев
2021-12-24 10:12

У нас ни в чём, так как мэппинг везде одинаковый. Можно и так, и так.

Нам бы сейчас отдельные папки помогли постепенно модуль за модулем перевести с аннотаций на атрибуты большой проект.

Ответить
Владимир Перепеченко
2021-12-24 11:28

Значит на производительность не повлияет указание одного src - Отлично!

Очень ценю Ваши ответы Дмитрий! 👊

Ответить
slo_nik
2021-12-21 23:01

После обновления react-scripts 4.0.3 -> 5.0.0 возникла ошибка:

Firefox cannot connect to the server ws://localhost:3000/ws.

Решается заменой в конфигах nginx

location /sockjs-node{...}

на

location /ws{...}

И добавлением в environment для frontend-node переменной

  • WDS_SOCKET_PORT=0

Без этой переменной не работает.

Ошибка больше в консоли не появлялась, "горячая" перезагрузка страницы работает.

Возможно кому-то поможет.

Ответить
Руслан
2022-01-05 13:56

Спасибо!

Ответить
Руслан
2022-02-11 09:04

Дима, когда примерно будет продолжение серии по Slim/React?

Ответить
Алексей
2022-03-13 13:07

Спасибо, и есть вопрос по атрибутам, в проекте по Symfony для swagger`а использовались аннотации, а как такие же анотации перевести в атрибуты? вот пример из вашего проекта используется php 8.1

   /**
     * @OA\Get(
     *     path="/work/tasks",
     *     tags={"Work Task"},
     *     @OA\Parameter(
     *         name="filter[author]",
     *         in="query",
     *         required=false,
     *         @OA\Schema(type="string"),
     *         style="form"
     *     ),
     *     @OA\Response(
     *         response=200,
     *         description="Success response",
     *         @OA\JsonContent(
     *             type="object",
     *             @OA\Property(property="items", type="array", @OA\Items(
     *                 @OA\Property(property="id", type="integer"),
     *                 @OA\Property(property="project", type="object",
     *                     @OA\Property(property="id", type="string"),
     *                     @OA\Property(property="name", type="string"),
     *                 ),
     *                 @OA\Property(property="date", type="string")
     *             )),
     *             @OA\Property(property="pagination", ref="#/components/schemas/Pagination"),
     *         )
     *     ),
     *     security={{"oauth2": {"common"}}}
     * )
     */
Ответить
Дмитрий Елисеев
2022-03-13 14:37

Аналогично, но с ключами вроде parameters и responses:

    #[OA\Get(
        path: '/work/tasks',
        tags: ['Work Task'],
        parameters: [
            new OA\Parameter(
                name: 'filter[author]',
                in: 'query',
                required: false,
                schema: new OA\Schema(type: 'string'),
                style: 'form'
            ),
        ],
        responses: [
            new OA\Response(
                response: 200,
                content: new OA\JsonContent(...)
            )
        ]
    )]
Ответить
Алексей
2022-03-13 15:54

понял, спасибо большое, к примеру выходит как то так

#[OAT\Get(
    path: '/profile',
    description: 'profile',
    tags: ['Profile'],
    responses: [
        new OAT\Response(
            response: 200,
            content: new OAT\JsonContent(
                properties: [
                    new OAT\Property(
                        property: 'time',
                        type: 'string'
                    ),
                    new OAT\Property(
                        property: 'result',
                        type: "object",
                        properties:[
                            new OAT\Property(property: 'title', type: 'string')
                        ]
                    )
                ]
            )
        )
    ]
)]

еще вопрос, phpStorm начиная с new OAT\Response подсвечивает все красным, однако код работает и документацию делает правильно и я не нашел плагинов которые бы ему объяснили что все норм

Ответить
Алексей
2022-03-13 22:41

Вопрос отпал сам собой, оказывается phpstorm 2021.2 так не умел, обновился до .3 и все отлично!

Ответить
Стариков Андрей
2023-01-28 06:26

Добрый день, заметил, что при переходе на атрибуты, правило final_class для php cs fixer перевело классы сущностей в final, так как в этой проверке настроено определение entity при помощи phpDoc. На dev окружение проблем с этим нет, но на prod сервере будет ошибка при создании прокси объектов. Чтобы не отключать это правило, у себя добавил к этим классам @final. Может стоит добавить какую-то проверку в make check, чтобы она проверяла такие возможны ошибки

Ответить
Дмитрий Елисеев
2023-02-07 09:26

Да, есть у них пока такой баг. Может в скором времени исправят.

Прокси-объекты создаются если в проекте мы из одной сущности лениво подгружаем ManyToOne связь вроде $comment->author или если в зависимых фикстурах используется getReference. У нас таких внешних связей не будет, так что нам final не помешает.

Ответить
Зарегистрируйтесь или войдите чтобы оставить комментарий

Или войти через:

Yandex
MailRu
GitHub
Google