Создание API на Symfony 5: Создание первого сервиса

preview_player
Показать описание
В этом ролике мы займемся созданием первого очень простого сервиса для отдачи книжных категорий. Подойдем к вопросу комплексно: напишем отдельный сервис, покроем его юнит-тестами, напишем контроллер для вызова сервиса, покроем его простеньким функциональным тестом, добавим фикстуры и сваггер. Помимо этого, углубимся немного в теорию по каждому пункту.

Рекомендации по теме
Комментарии
Автор

Отличное качество материала, спасибо за ваши труды 🙂

qoonmax
Автор

01:06 Добавление категорий
3:35 ... и репозитория
4:15 Сервисы
5:50 BookCategoryResponse
11:16 Контроллер для категорий
13:30 migrations:diff

XanderEVGs
Автор

В данном видео не согласен с реализацией сервисного слоя, считаю, что они должны возвращать данные, а респонс уже должен готовиться на стороне контроллера, в чём и заключается задача контроллера. Если же сервис возвращает респонс, то он мешается с http слоем и его нельзя переиспользовать в других местах. Понимаю, что в рамках обучения многим можно пренебречь, но подобного рода решения порой создают трудности и лучше от них отказываться в начале разработки. В остальном же, автору спасибо, курс очень полезный!

obsidok
Автор

По поводу интерфейсов - реализацию сервиса можно загнать в контроллер, так как с инфраструктуры обращаемся к бизнес-логике, в этом проблемы нет, а вот то, что сервис зависит от имплементации репозитория уже плохо, так как бизнес-логика зависит от инфры, тут как раз и нужен Dependency Inversion. Как минимум будет не так проблемно писать тесты

hgfyos
Автор

Спасибо за контент! А можно все это в гит ?)

krbftnw
Автор

Пустую бд не обязательно генерить для тестов, достаточно в транзакции запихать, есть на это уже, либы, вроде как

wbdhpsx
Автор

подписался, колокольчик поставил. Есть актуальный вопрос: на проекте накопились аннотации. Как их переписать в атрибуты, если только не руцями - мануально. Регуляркой или баш-скриптом или уже есть что-то готовое?

oleksandrtishchenko
Автор

Особо спасибо за тесты. Однако у меня вопрос - нельзя же оставлять в сущности setId(int $id), что с этим делать?

solvex
Автор

Благодарю за подробные уроки на доступном языке!
Всё очень интересно, но на 12й минуте выскочила вереница ошибок. Танцы с бубном и щепотка "магии" от Алисы оказались бессильны...
RuntimeException:
The definition for "BookCategoryService" has no class. If you intend to inject this service dynamically at runtime, please mark it as synthetic=true. If this is an abstract definition solely used by child definitions, please add abstract=true, otherwise specify a class to get rid of this error.

aleksandervitalevich
Автор

руки бы оторвать за стрелочные функции

delifeful
Автор

BookCategoryListResponse - получается это агрегатор, т.е. в него сейчас положили только items, а потом положим его чего нибудь - верно?

nlujdto
Автор

Почему в сущности BookCategory свойство id может быть null (private ?int id) ? Или это для всех сущностей так нужно писать?

yrrqwen
Автор

Все круто, спасибо большое! Но как по мне с документированием немного перебор. 3 зависимости лишних тащить как то стремно. Проще подключить confluence, тем более он вроде как бесплатный до 5 участников.

saveljevroman
Автор

Привет, без создания сеттера в сущности нет других методов, замокать этот метод в самом юнит тесте нельзя? Автогенерируемое (доктриной например) значение id в сущности сеттер будет лишним

wbdhpsx
Автор

Да уж. В реальной жизни DDD в проектах на PHP не используется. Хотя на собеседованиях любят спрашивать про DDD.

yrrqwen
Автор

10:00 что то не нравится мне такой подход, плюс минус такой же результат мы не можем достичь используя сериализатор? Получится обычный массив, а не массив BookItems, так ли это критично?

Например если я захочу написать getArchiveCategories(), мне придется маппить со всеми этими ->getFieldName() в каждом таком методе(или писать отдельный маппер?)
Хотелось бы что то типа $items = BookMapper->map($categories, [список_нужных_полей]), но как это сделать что то не соображу, кроме как вот так:

$items = $serializer->normalize($items, false, ['id', 'title', 'author' => ['id', 'fio']]);

XanderEVGs
Автор

Классический MVC, но я так и непонял, почему не по классическим практикам Симфони? Почему Гетеры и Сетеры не поместить в класс сущности. Простейший запрос в контролер. Не совсем понял философию

oleksandrtishchenko
Автор

Все-таки жаль что DDD не заимплементил, цены не было бы таким уроками. На Youtube ничего по этой теме не нашел.

mspcvju
Автор

На моменте 53:42, во время установки api-doc-bundle, получаю следующую проблему:

Problem 1
- nelmio/api-doc-bundle[2.13.3, ..., 2.x-dev] require symfony/twig-bundle ~2.3|~3.0|~4.0 -> satisfiable by symfony/symfony[2.0.6].
- nelmio/api-doc-bundle[2.11.0, ..., 2.13.2] require symfony/twig-bundle ~2.3|~3.0 -> satisfiable by symfony/symfony[2.0.6].
- nelmio/api-doc-bundle[2.10.0, ..., 2.10.3] require symfony/twig-bundle ~2.3 -> satisfiable by symfony/symfony[2.0.6].
- nelmio/api-doc-bundle[2.4.3, ..., 2.9.0] require symfony/twig-bundle ~2.1 -> satisfiable by symfony/symfony[2.0.6].
- nelmio/api-doc-bundle[2.2.1, ..., 2.4.2] require symfony/framework-bundle ~2.1 -> satisfiable by symfony/symfony[2.0.6].
- nelmio/api-doc-bundle[2.1.0, ..., 2.2.0] require symfony/framework-bundle ~2.1, <2.3-dev -> satisfiable by symfony/symfony[2.0.6].
- nelmio/api-doc-bundle 2.0.1 requires symfony/framework-bundle >=2.1, <2.3-dev -> satisfiable by symfony/symfony[2.0.6].
- nelmio/api-doc-bundle 2.0.0 requires symfony/framework-bundle 2.1.* -> satisfiable by symfony/symfony[2.0.6].
- nelmio/api-doc-bundle 1.0.1 requires symfony/symfony 2.0.* -> satisfiable by symfony/symfony[2.0.4, ..., 2.0.x-dev].
- nelmio/api-doc-bundle 1.0.0 requires symfony/framework-bundle 2.0.* -> satisfiable by symfony/symfony[2.0.4, ..., 2.0.x-dev].
- symfony/skeleton dev-master conflicts with symfony/symfony 2.0.6.
- nelmio/api-doc-bundle[v3.0.0-BETA1, ..., v3.0.0-BETA4] require php ~7.0|~7.1 -> your php version (8.2.1) does not satisfy that requirement.
- nelmio/api-doc-bundle[v3.0.0, ..., v3.5.0] require php ^7.0 -> your php version (8.2.1) does not satisfy that requirement.
- nelmio/api-doc-bundle[v3.6.0, ..., v3.7.4, v4.0.0-BETA1, ..., v4.0.1] require php ^7.1 -> your php version (8.2.1) does not satisfy that requirement.
- symfony/symfony[v2.0.15, ..., 2.0.x-dev] require doctrine/common >=2.1, <2.3-dev -> found doctrine/common[2.1.3, ..., 2.2.x-dev] but these were not loaded, likely because it conflicts with another require.
- symfony/symfony[2.0.7, ..., v2.0.14] require doctrine/common 2.1.* -> found doctrine/common[2.1.3, 2.1.4, 2.1.x-dev] but these were not loaded, likely because it conflicts with another require.
- nelmio/api-doc-bundle[dev-TEST, v3.8.0, ..., 3.x-dev] require symfony/options-resolver ^3.4.4|^4.0|^5.0 -> found symfony/options-resolver[v3.4.4, ..., 3.4.x-dev, v4.0.0-BETA1, ..., 4.4.x-dev, v5.0.0-BETA1, ..., 5.4.x-dev] but these
were not loaded, likely because it conflicts with another require.
- nelmio/api-doc-bundle[v4.1.0, ..., v4.2.0] require symfony/options-resolver ^4.4|^5.0 -> found symfony/options-resolver[v4.4.0-BETA1, ..., 4.4.x-dev, v5.0.0-BETA1, ..., 5.4.x-dev] but these were not loaded, likely because it confli
cts with another require.
- nelmio/api-doc-bundle[dev-ROOTCONTEXT, dev-master, v4.3.0, ..., 4.x-dev] require doctrine/annotations ^1.11 -> found doctrine/annotations[1.11.0, ..., 1.15.x-dev] but it conflicts with your root composer.json require (^2.0).
- symfony/skeleton is present at version dev-master and cannot be modified by Composer
- Root composer.json requires nelmio/api-doc-bundle * -> satisfiable by nelmio/api-doc-bundle[dev-master, dev-ROOTCONTEXT, dev-TEST, 1.0.0, 1.0.1, 2.0.0, ..., 2.x-dev, v3.0.0-BETA1, ..., 3.x-dev, v4.0.0-BETA1, ..., 4.x-dev].

Пробовал с изминениями зависимостей (-W), но безуспешно( Подскажите, пожалуйста, как это можно исправить?

ejlgepl
Автор

я вот смотрю и удивляюсь, к чему так всё усложнять? на вывод списка категорий столько классов и функций создано. Жесть какая-то. Вот и думай: почему современные сайты крупных компаний так тупят люто.... объясните, зачем так усложнять?

yaslonane