โครงกระดูก Slim 4 Framework ที่ขับเคลื่อนด้วยเหตุการณ์โดยใช้ AMQP และ CQRS
โปรไฟล์การติดตั้งเริ่มต้นไม่มีตัวอย่าง คุณควรใช้โปรไฟล์นี้หากคุณรู้ว่ามีอะไรเกิดขึ้นและต้องการเริ่มต้นด้วยกระดานชนวนที่สะอาด
> 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 ;
}
}เอกสารฉบับเต็ม
โครงกระดูกอนุญาตให้คุณใช้คำสั่งและตัวจัดการคำสั่งเพื่อดำเนินการ 2 เหล่านี้มาเป็นคู่เสมอเมื่อสร้างคำสั่งใหม่ในรูปแบบการเขียนจะต้องสร้างตัวจัดการคำสั่งที่สอดคล้องกันเช่นกัน
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.
}
}เอกสารฉบับเต็ม
การใช้งาน AMQP ที่เลือกสำหรับโครงการนี้คือ RabbitMQ แต่สามารถเปลี่ยนเป็นตัวอย่างได้อย่างง่ายดายเช่นโซลูชัน AMQP ของ Amazon
#[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เอกสารฉบับเต็ม
ในการจัดการการโยกย้ายฐานข้อมูลจะใช้แพ็คเกจหลักคำสอน/การย้ายถิ่น
#[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 ,
) {
}
// ...
}คุณสามารถให้หลักคำสอนสร้างการย้ายถิ่นให้คุณได้โดยการเปรียบเทียบสถานะปัจจุบันของสคีมาฐานข้อมูลของคุณกับข้อมูลการแมปที่กำหนดโดยใช้ ORM แล้วดำเนินการโยกย้ายนั้น
> docker-compose run --rm php-cli vendor/bin/doctrine-migrations diff
> docker-compose run --rm php-cli vendor/bin/doctrine-migrations migrateเอกสารฉบับเต็ม
เอ็นจิ้นเทมเพลตที่เลือกสำหรับโครงการนี้คือกิ่งไม้และสามารถใช้เพื่อแสดงผลที่เกี่ยวข้องกับ 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 ;
}
}เอกสารฉบับเต็ม
เรียนรู้เพิ่มเติมได้ที่ลิงค์เหล่านี้:
โปรดดูรายละเอียดที่มีส่วนร่วม