Coder Social home page Coder Social logo

blry / symfonycleanarchitecture Goto Github PK

View Code? Open in Web Editor NEW
6.0 1.0 0.0 151 KB

:rocket: Symfony Clean Architecture Template: A starting point for Clean Architecture with Symfony 6

PHP 91.67% Twig 1.77% Dockerfile 5.13% Shell 1.44%
clean-architecture ddd domain-driven-design php php8 symfony docker non-root

symfonycleanarchitecture's Introduction

Symfony Clean Architecture

This repository serves as a foundational Symfony Clean Architecture template, drawing inspiration from the ideas of Robert C. Martin (Uncle Bob) on Clean Architecture and Domain-Driven Design (DDD) by Robert C. Martin.

The template demonstrates an exemplary implementation of a users API using Symfony Messenger, league/oauth2-server-bundle and knpuniversity/oauth2-client-bundle bundles.

It includes the implementation of the social grant, designed specifically to handle social login functionalities. By utilizing the social grant, users gain the ability to log in to the application using any OAuth2 client provider, such as Telegram. If you wish to integrate additional OAuth2 client providers, you can easily do so by modifying the configuration in config/packages/knpu_oauth2_client.yaml.

Author GitHub release GitHub repository Docker hub GitHub repository Docker hub Docker hub Docker hub

Table Of Contents

Project structure

The project follows a Clean Architecture structure to ensure a clear separation of concerns. The main directories are:

  • api: Contains the application source code.
    • src/Domain: The core domain logic and entities of the application.
    • src/Application:
      • Bounded Context/UseCase: Use Cases represent the actions which encapsulate the business logic and interact with the domain layer to achieve specific tasks.
      • Bounded Context/DomainEventHandler: Domain event handlers are responsible for handling domain events raised within the domain layer.
      • Bounded Context/IntegrationEventHandler: Integration event handlers are responsible for handling integration events that are received from other bounded contexts or external systems.
    • src/Infrastructure: External tools and frameworks integration, such as databases, third-party services, etc.
  • docker: Contains configs related to docker containers
    • shared: Shared files

Give a Star! ⭐

If you like or are using this project to learn or start your solution, please give it a star. Thanks!

Getting Started

Requirements

Ensure you have the following installed:

and these ports are open:

Installation

  1. Clone this repository to your local machine:
git clone https://github.com/pikaso443/retrans-live
  1. Create .env file in the root folder and set your variables by copying .env.dev_local
  • TRAEFIK_TOKEN - Traefik token
  • TRAEFIK_API_HOST - Traefik will use the variable to create a certificate with Let's Encrypt. Make sure DNS records are set correctly.
  1. Create secrets in docker/shared/secrets/:
  • db_root_password, db_password - DB root and application user passwords
  • oauth2_encryption.key, oauth2_private.key, oauth2_public.key - OAuth2 Server Encryption, Private and Public keys
  • telegram_bot_token - OAuth2 Client Telegram Bot token
  1. Now you can run the project, install dependencies, run migrations and fixtures:
docker-compose up -d
docker-compose exec php-cli bash -ilc "cd /var/www/api && composer install && bin/console do:mi:mi --no-interaction"
docker-compose restart
docker-compose exec php-cli bash -ilc "/var/www/api/bin/console do:fi:lo --no-interaction"
  1. Done! ⭐
  • Traefik starts on port 80, 443, 8080. Access https://TRAEFIK_API_HOST using any browser
  • Nginx starts on port 8082: localhost:8082/doc
  • Mailhog HTTP server starts on port 8025: localhost:8025

Learn more

Domain Events vs Integration Events vs Infrastructure Events

In the context of Domain-Driven Design (DDD) and event-driven architectures, Domain Events, Integration Events and Infrastructure Events are mechanisms for handling events and interactions within a system. However, they serve different purposes and are used in different contexts.

Domain Events

Domain Events are a core concept in DDD and represent significant state changes or business occurrences within the domain model. They are used to communicate important business events or facts that have happened within the application's domain. Domain Events are raised from within the domain entities or aggregate roots and are typically used to trigger side effects or update other parts of the system.

Example of a Domain Event: UserCreatedEvent, which is raised when a new user is created. Other DomainEventHandlers within the same domain model can listen to this event (e.g. SendEmailOnUserCreatedEventHandler).

Integration Events

Integration Events are events that facilitate communication and integration between different bounded contexts or external systems. They are used to signal changes or facts to other parts of the system, often outside the core domain.

Example of a Integration Event: UserCreatedIntegrationEvent, which is mapped from UserCreatedEvent in IntegrationEventMapper and dispatched by DomainEventSubscriber. An IntegrationEventHandler from another bounded context is subscribed to it.

Infrastructure Events

Infrastructure Events are events which are raised by the framework (e.g. Doctrine's LifecycleEventArgs which is handled by DomainEventSubscriber).

How to make an Event to be asynchronous?

Integration Events are asynchronous by default. In order to make a Domain Event asynchronous, modify messenger.php:

'routing' => [
    \Symfony\Component\Mailer\Messenger\SendEmailMessage::class => ['async'],
    \Symfony\Component\Notifier\Message\MessageInterface::class => ['async'],
    \App\Application\Common\IntegrationEvent\IntegrationEventInterface::class => ['async'],
    \App\Domain\User\Event\UserCreatedEvent::class => ['async'],
],

Also, you may want to make a Handler to work only with asynchronous events:

#[AsMessageHandler(fromTransport: 'async')]
readonly class YourEventHandler implements HandlerInterface
{
    public function __invoke(Input $input): void {}
}

Related links

symfonycleanarchitecture's People

Contributors

blry avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.