Создаем CQRS сервис с нуля: Spiral, Symfony Messenger и PHP Attributes | Полное руководство
HTML-код
- Опубликовано: 6 июн 2024
- 🚀 Присоединяйтесь к нашему стриму, где мы шаг за шагом создаем CQRS сервис с использованием Spiral Framework, Symfony Messenger и PHP Attributes. Этот стрим будет интересен как начинающим, так и опытным разработчикам, желающим глубже понять архитектуру CQRS.
🔍 Что мы рассмотрим:
0:00 Начинаем стрим
3:00 План стрима
3:46 Что такое CQRS. Смотрим картинки
13:00 Создание интерфесов
17:00 Установка Symfony Messenger
18:30 Создание перовго теста
21:56 Создание перовго Command Handler
25:10 Создание Command Bus
30:15 Изучаем Symfony Message Bus
37:00 Создание локатора команд
51:00 Проверка работы локатора
51:30 Настройка PHP атрибута
54:30 Spiral Tokenizer
1:05:00 Проверка работы локатора с PHP атрибуттами
1:06:15 Создание Operation Stamp
1:08:50 Создание Query Bus
1:12:50 Изучение Middleware для Message Bus
1:21:40 Доработка локатора Query команд
1:33:50 Создание первого Query Handler
1:40:30 Варианты использования Query Bus
1:43:15 Проверка работы Query Handler
1:46:15 Про Spiral Prototype
1:54:05 Для чего нужен Operation Uuid
1:59:25 Создаем консольную команду
2:03:00 Transactional Command Bus
2:11:00 Command Listener
2:30:30 Советы по передаваемым данным
Код со стрима находится здесь: github.com/php-fart/cqrs-app
Ссылка на наш дискорд, где мы проводим стримы и где можно с нами поболтать
/ discord
Наш канал: t.me/php_fart
Наши твиттеры:
/ butsch - Pavel Buchnev
/ roxblnfk - Aleksei Gagarin
#php #spiral #development #symfony
👍 Если вам нравится контент, подписывайтесь на канал и ставьте лайк. Не забудьте оставить свой комментарий! - Наука
Спасибо огромное! Почерпнул для себя массу полезного!
Если создавать пакет CQRS (Command Query Responsibility Segregation), было бы здорово сделать так, чтобы мидлвары выносились в отдельные пакеты, как это реализовано в Tactician.
Код со стрима выложил в репозиторий: github.com/php-fart/cqrs-app
Предлагайте идеи для будущих стримов
Было бы здорово иметь список мидлваров и возможность указывать, какие из них использовать для конкретной команды через атрибуты. #[middleware list [handler, validator]]
Да, это можно сделать. Через middleware)
@@php-farttime я такое уже писал для своего Bus Удобно. И решает проблему (Igor Markin
InMemoryCommandBus, KafkaCommandBus и тд)
Дополнение.. #[middleware list [ ValidatorMiddleware, TransactionMiddleware, EventMiddleware,Handler]]
ValidatorMiddleware: проверяет команду на соответствие требованиям.
TransactionMiddleware: оборачивает выполнение команды в транзакцию.
EventMiddleware: обрабатывает события после выполнения команды.
HandlerMiddleware: выполняет саму команду, вызывая соответствующий обработчик.
порядок запуска миделверов будет порятку их добавление в list
Функция установки мидлваров:
private function setMiddlewares(object $message) {
$reflectionClass = new \ReflectionClass($message);
// Получаем аннотации [Middlewares]
$middlewaresAttributes = $reflectionClass->getAttributes(Middlewares::class);
if (!empty($middlewaresAttributes)) {
// Получаем первую аннотацию [Middlewares]
$middlewaresAttribute = $middlewaresAttributes[0];
// Извлекаем аргументы аннотации
$middlewaresArguments = $middlewaresAttribute->getArguments();
// Теперь у вас есть доступ к массиву промежуточных слоев
$middlewaresList = $middlewaresArguments['list'];
foreach ($middlewaresList as $middlewareName) {
$this->middlewares->addMiddleware($middlewareName);
}
}
}
Мой пример команды:
#[Middlewares(list: [ValidationBusMiddleware::class, CommandHandlerMiddleware::class])]
#[Handler(className: CreateUserHandler::class)]
#[Validation(className: CreateUserValidator::class)]
final class CreateUserCommand implements ICommand {
public function __construct(
#[Assert\NotBlank]
public readonly string $uuid,
#[Assert\NotBlank]
public readonly string $login,
#[Assert\NotBlank]
#[Assert\Email(message: 'The email {{ value }} is not a valid email.')]
public readonly string $email,
#[Assert\Length(min: 6)]
#[Assert\NotBlank]
public readonly string $password,
#[Assert\NotBlank]
public readonly string $name,
#[Assert\NotBlank]
public readonly string $gender,
) {
}
}
Было бы проще заменить dispatchMany на middlewareEvent, который по имени команды подключает соответствующие мидлвары, а затем запускает их. Эта мой пример