robiningelbrecht / php-slim-skeleton
dev-master
2023-08-29 13:12 UTC
Requires
- php: ^8.2
- ext-json: *
- ext-pcntl: *
- ext-sockets: *
- doctrine/dbal: ^3.6
- doctrine/migrations: ^3.5
- doctrine/orm: ^2.12
- filp/whoops: ^2.15
- lcobucci/clock: ^2.2
- php-amqplib/php-amqplib: ^3.2
- php-di/php-di: ^7.0
- php-di/slim-bridge: ^3.3
- ramsey/uuid: ^4.7
- slim/psr7: ^1.6
- slim/slim: ^4.11
- symfony/cache: ^6.1
- symfony/console: ^6.1
- symfony/finder: ^6.1
- thecodingmachine/safe: ^2.2
- twig/twig: ^3.4
- vlucas/phpdotenv: ^5.4
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.16
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^10.1
- robiningelbrecht/phpunit-pretty-print: ^1.2.0
- spatie/phpunit-snapshot-assertions: ^5.0
This package is auto-updated.
Last update: 2024-08-29 15:15:57 UTC
README
使用 AMQP 和 CQRS 的事件驱动 Slim 4 框架骨架
安装
默认安装配置
默认安装配置没有示例。如果您对此有所了解,并希望从头开始,应使用此配置。
> composer create-project robiningelbrecht/php-slim-skeleton [app-name] --no-install --ignore-platform-reqs --stability=dev # Build docker containers > docker-compose up -d --build # Install dependencies > docker-compose run --rm php-cli composer install
完整安装配置
完整安装配置包含一个完整的工作示例。
> composer create-project robiningelbrecht/php-slim-skeleton:dev-master-with-examples [app-name] --no-install --ignore-platform-reqs --stability=dev # Build docker containers > docker-compose up -d --build # Install dependencies > docker-compose run --rm php-cli composer install # Initialize example > docker-compose run --rm php-cli composer example:init # Start consuming the voting example queue > docker-compose run --rm php-cli bin/console app:amqp:consume add-vote-command-queue
一些示例
注册新路由
namespace App\Controller; class UserOverviewRequestHandler { public function __construct( private readonly UserOverviewRepository $userOverviewRepository, ) { } public function handle( ServerRequestInterface $request, ResponseInterface $response): ResponseInterface { $users = $this->userOverviewRepository->findonyBy(/*...*/); $response->getBody()->write(/*...*/); return $response; } }
转到 config/routes.php
并为您的 RequestHandler 添加路由
return function (App $app) { // Set default route strategy. $routeCollector = $app->getRouteCollector(); $routeCollector->setDefaultInvocationStrategy(new RequestResponseArgs()); $app->get('/user/overview', UserOverviewRequestHandler::class.':handle'); };
控制台命令
控制台应用程序使用 Symfony 控制台组件来利用 CLI 功能。
#[AsCommand(name: 'app:user:create')] class CreateUserConsoleCommand extends Command { protected function execute(InputInterface $input, OutputInterface $output): int { // ... return Command::SUCCESS; } }
域命令和命令处理器
该骨架允许您使用命令和命令处理器来执行操作。这两个总是成对出现,当在写入模型中创建新命令时,必须同时创建相应的命令处理器。
创建新命令
namespace App\Domain\WriteModel\User\CreateUser; class CreateUser extends DomainCommand { }
创建相应的命令处理器
namespace App\Domain\WriteModel\User\CreateUser; #[AsCommandHandler] class CreateUserCommandHandler implements CommandHandler { public function __construct( ) { } public function handle(DomainCommand $command): void { assert($command instanceof CreateUser); // Do stuff. } }
事件驱动
该项目的主旨在于一切或可以成为事件驱动的。默认情况下不提供事件源。
创建新事件
class UserWasCreated extends DomainEvent { public function __construct( private UserId $userId, ) { } public function getUserId(): UserId { return $this->userId; } }
记录事件
class User extends AggregateRoot { private function __construct( private UserId $userId, ) { } public static function create( UserId $userId, ): self { $user = new self($userId); $user->recordThat(new UserWasCreated($userId)); return $user; } }
发布事件
class UserRepository extends DbalAggregateRootRepository { public function add(User $user): void { $this->connection->insert(/*...*/); $this->publishEvents($user->getRecordedEvents()); } }
监听事件
#[AsEventListener(type: EventListenerType::PROCESS_MANAGER)] class UserNotificationManager extends ConventionBasedEventListener { public function reactToUserWasCreated(UserWasCreated $event): void { // Send out some notifications. } }
使用 RabbitMQ 异步处理命令
该项目选择的 AMQP 实现是 RabbitMQ,但它可以轻松切换到例如亚马逊的 AMQP 解决方案。
注册新队列
#[AsEventListener(type: EventListenerType::PROCESS_MANAGER)] class UserCommandQueue extends CommandQueue { }
排队命令
class YourService { public function __construct( private readonly UserCommandQueue $userCommandQueue ) { } public function aMethod(): void { $this->userCommandQueue->queue(new CreateUser(/*...*/)); } }
消费队列
> docker-compose run --rm php-cli bin/console app:amqp:consume user-command-queue
数据库迁移
为了管理数据库迁移,使用了 doctrine/migrations 包。
#[Entity] class User extends AggregateRoot { private function __construct( #[Id, Column(type: 'string', unique: true, nullable: false)] private readonly UserId $userId, #[Column(type: 'string', nullable: false)] private readonly Name $name, ) { } // ... }
您可以使用 Doctrine 通过比较您的数据库模式当前状态与使用 ORM 定义的映射信息来为您生成迁移,然后执行该迁移。
> docker-compose run --rm php-cli vendor/bin/doctrine-migrations diff > docker-compose run --rm php-cli vendor/bin/doctrine-migrations migrate
模板引擎
该项目选择的模板引擎是 Twig,可用于渲染任何 HTML 相关的内容。
创建模板
<h1>Users</h1> <ul> {% for user in users %} <li>{{ user.username|e }}</li> {% endfor %} </ul>
渲染模板
class UserOverviewRequestHandler { public function __construct( private readonly Environment $twig, ) { } public function handle( ServerRequestInterface $request, ResponseInterface $response): ResponseInterface { $template = $this->twig->load('users.html.twig'); $response->getBody()->write($template->render(/*...*/)); return $response; } }
文档
在这些链接中了解更多信息
使用此骨架的项目
贡献
请参阅 CONTRIBUTING 了解详细信息。