Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/codelytv/php-ddd-example
ππ― Hexagonal Architecture + DDD + CQRS in PHP using Symfony 7
https://github.com/codelytv/php-ddd-example
behat bounded-context codely codelytv cqrs ddd docker doctrine domain-driven-design hexagonal-architecture laravel microservice microservices-architecture monorepo php php8 phpunit symfony symfony5 testing
Last synced: 7 days ago
JSON representation
ππ― Hexagonal Architecture + DDD + CQRS in PHP using Symfony 7
- Host: GitHub
- URL: https://github.com/codelytv/php-ddd-example
- Owner: CodelyTV
- Created: 2016-11-17T12:56:16.000Z (about 8 years ago)
- Default Branch: main
- Last Pushed: 2024-08-06T15:12:23.000Z (6 months ago)
- Last Synced: 2024-10-29T14:53:44.832Z (3 months ago)
- Topics: behat, bounded-context, codely, codelytv, cqrs, ddd, docker, doctrine, domain-driven-design, hexagonal-architecture, laravel, microservice, microservices-architecture, monorepo, php, php8, phpunit, symfony, symfony5, testing
- Language: PHP
- Homepage: https://pro.codely.tv/library/ddd-en-php
- Size: 2.04 MB
- Stars: 2,979
- Watchers: 82
- Forks: 1,081
- Open Issues: 57
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
Awesome Lists containing this project
README
ππ― Hexagonal Architecture, DDD & CQRS in PHP
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## π Environment Setup
### π³ Needed tools
1. [Install Docker](https://www.docker.com/get-started)
2. Clone this project: `git clone https://github.com/CodelyTV/php-ddd-example php-ddd-example`
3. Move to the project folder: `cd php-ddd-example`### π οΈ Environment configuration
1. Create a local environment file (`cp .env .env.local`) if you want to modify any parameter
### π₯ Application execution
1. Install all the dependencies and bring up the project with Docker executing: `make build`
2. Then you'll have 3 apps available (2 APIs and 1 Frontend):
1. [Mooc Backend](apps/mooc/backend): http://localhost:8030/health-check
2. [Backoffice Backend](apps/backoffice/backend): http://localhost:8040/health-check
3. [Backoffice Frontend](apps/backoffice/frontend): http://localhost:8041/health-check### β Tests execution
1. Install the dependencies if you haven't done it previously: `make deps`
2. Execute PHPUnit and Behat tests: `make test`## π©βπ» Project explanation
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.### β±οΈ Bounded Contexts
- [Mooc](src/Mooc): Place to look in if you wanna see some code π. Massive Open Online Courses public platform with users, videos, notifications, and so on.
- [Backoffice](src/Backoffice): Here you'll find the use cases needed by the Customer Support department in order to manage users, courses, videos, and so on.### π― Hexagonal Architecture
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:```scala
$ tree -L 4 srcsrc
|-- 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
```#### Repository pattern
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](src/Mooc/Courses/Domain/CourseRepository.php)
and its implementation [here](src/Mooc/Courses/Infrastructure/Persistence/DoctrineCourseRepository.php).### Aggregates
You can see an example of an aggregate [here](src/Mooc/Courses/Domain/Course.php). All aggregates should
extend the [AggregateRoot](src/Shared/Domain/Aggregate/AggregateRoot.php).### Command Bus
There is 1 implementations of the [command bus](src/Shared/Domain/Bus/Command/CommandBus.php).
1. [Sync](src/Shared/Infrastructure/Bus/Command/InMemorySymfonyCommandBus.php) using the Symfony Message Bus.### Query Bus
The [Query Bus](src/Shared/Infrastructure/Bus/Query/InMemorySymfonyQueryBus.php) uses the Symfony Message Bus.
### Event Bus
The [Event Bus](src/Shared/Infrastructure/Bus/Event/InMemory/InMemorySymfonyEventBus.php) uses the Symfony Message Bus.
The [MySql Bus](src/Shared/Infrastructure/Bus/Event/MySql/MySqlDoctrineEventBus.php) uses a MySql+Pulling as a bus.
The [RabbitMQ Bus](src/Shared/Infrastructure/Bus/Event/RabbitMq/RabbitMqEventBus.php) uses RabbitMQ C extension.## π± Monitoring
Every time a domain event is published it's exported to Prometheus. You can access to the Prometheus panel [here](http://localhost:9999/).
## π€ Contributing
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 :)## π€© Extra
This code was shown in the [From framework coupled code to #microservices through #DDD](http://codely.tv/blog/screencasts/codigo-acoplado-framework-microservicios-ddd) talk and doubts where answered in the [DDD y CQRS: Preguntas Frecuentes](https://codely.com/blog/ddd-cqrs-preguntas-frecuentes) video.
π₯ Used in the CodelyTV Pro courses:
- [πͺπΈ DDD in PHP](https://pro.codely.tv/library/ddd-en-php/about/)
- [πͺπΈ Arquitectura Hexagonal](https://pro.codely.tv/library/arquitectura-hexagonal/66748/about/)
- [πͺπΈ CQRS: Command Query Responsibility Segregation](https://pro.codely.tv/library/cqrs-command-query-responsibility-segregation-3719e4aa/62554/about/)
- [πͺπΈ ComunicaciΓ³n entre microservicios: Event-Driven Architecture](https://pro.codely.tv/library/comunicacion-entre-microservicios-event-driven-architecture/74823/about/)## π remember to visit our courses
- [Courses codely](https://codely.com/cursos)