๐๐ฏ Hexagonal Architecture + DDD + CQRS in PHP using Symfony 7
Example of a PHP application using Domain-Driven Design (DDD) and Command Query Responsibility Segregation
(CQRS) principles keeping the code as simple as possible.
Take a look, play and have fun with this.
Stars are welcome ๐
View Demo
ยท
Report a bug
ยท
Request a feature
git clone https://github.com/CodelyTV/php-ddd-example php-ddd-example
cd php-ddd-example
cp .env .env.local
) if you want to modify any parametermake build
make deps
make test
This project tries to be a MOOC (Massive Open Online Course) platform. Itโs decoupled from any framework, but it has
some Symfony and Laravel implementations.
This repository follows the Hexagonal Architecture pattern. Also, itโs structured using modules
.
With this, we can see that the current structure of a Bounded Context is:
$ tree -L 4 src
src
|-- Mooc // Company subdomain / Bounded Context: Features related to one of the company business lines / products
| `-- Videos // Some Module inside the Mooc context
| |-- Application
| | |-- Create // Inside the application layer all is structured by actions
| | | |-- CreateVideoCommand.php
| | | |-- CreateVideoCommandHandler.php
| | | `-- VideoCreator.php
| | |-- Find
| | |-- Trim
| | `-- Update
| |-- Domain
| | |-- Video.php // The Aggregate of the Module
| | |-- VideoCreatedDomainEvent.php // A Domain Event
| | |-- VideoFinder.php
| | |-- VideoId.php
| | |-- VideoNotFound.php
| | |-- VideoRepository.php // The `Interface` of the repository is inside Domain
| | |-- VideoTitle.php
| | |-- VideoType.php
| | |-- VideoUrl.php
| | `-- Videos.php // A collection of our Aggregate
| `-- Infrastructure // The infrastructure of our module
| |-- DependencyInjection
| `-- Persistence
| `--MySqlVideoRepository.php // An implementation of the repository
`-- Shared // Shared Kernel: Common infrastructure and domain shared between the different Bounded Contexts
|-- Domain
`-- Infrastructure
Our repositories try to be as simple as possible usually only containing 2 methods search
and save
.
If we need some query with more filters we use the Specification
pattern also known as Criteria
pattern. So we add a
searchByCriteria
method.
You can see an example here
and its implementation here.
You can see an example of an aggregate here. All aggregates should
extend the AggregateRoot.
There is 1 implementations of the command bus.
The Query Bus uses the Symfony Message Bus.
The Event Bus uses the Symfony Message Bus.
The MySql Bus uses a MySql+Pulling as a bus.
The RabbitMQ Bus uses RabbitMQ C extension.
Every time a domain event is published itโs exported to Prometheus. You can access to the Prometheus panel here.
There are some things missing (add swagger, improve documentationโฆ), feel free to add this if you want! If you want
some guidelines feel free to contact us ๐
This code was shown in the From framework coupled code to #microservices through #DDD talk and doubts where answered in the DDD y CQRS: Preguntas Frecuentes video.
๐ฅ Used in the CodelyTV Pro courses: