Hexagonal Maker Bundle
Symfony Maker Bundle for Hexagonal Architecture (Ports & Adapters)
โจ 19 maker commands | ๐ Pure Domain | ๐ฏ CQRS Pattern | ๐๏ธ Full Layer Coverage
Why Hexagonal Architecture?
Hexagonal architecture (aka Ports & Adapters) helps you build maintainable, testable applications by:
- ๐ Pure Domain Isolation - Business logic independent of frameworks
- ๐ฏ Dependency Control - Infrastructure depends on domain, not vice versa
- โก Testing Speed - Unit tests run 1000x faster (no database needed)
- ๐ Technology Freedom - Swap databases, frameworks without touching business logic
- ๐ฐ Cost Predictability - Features cost consistent time, no technical debt tax
โก Quick Start (2 minutes)
Step 1: Install
composer require ahmed-bhs/hexagonal-maker-bundle --dev
Step 2: Generate your first module
# Create a User Registration module
bin/console make:hexagonal:entity user/account User
bin/console make:hexagonal:repository user/account User
bin/console make:hexagonal:command user/account register --factory
bin/console make:hexagonal:controller user/account RegisterUser /users/register
Step 3: Configure Doctrine mapping
# config/packages/doctrine.yaml
doctrine:
orm:
mappings:
UserAccount:
type: yml
dir: '%kernel.project_dir%/src/User/Account/Infrastructure/Persistence/Doctrine/Orm/Mapping'
prefix: 'App\User\Account\Domain\Model'
Result: Complete hexagonal module with pure domain, CQRS commands, and web controllers! ๐
Features
19 Maker Commands
Generate complete hexagonal architecture with a single command:
| Layer | Maker | What it generates |
|---|---|---|
| Domain | make:hexagonal:entity |
Pure PHP entities + YAML mapping |
| Domain | make:hexagonal:value-object |
Immutable value objects |
| Domain | make:hexagonal:exception |
Business exceptions |
| Application | make:hexagonal:command |
CQRS commands + handlers |
| Application | make:hexagonal:query |
CQRS queries + handlers + responses |
| Application | make:hexagonal:repository |
Repository port + Doctrine adapter |
| UI | make:hexagonal:controller |
Web controllers |
| UI | make:hexagonal:form |
Symfony forms |
| UI | make:hexagonal:cli-command |
Console commands |
| Tests | make:hexagonal:use-case-test |
Use case tests |
| Rapid | make:hexagonal:crud |
Complete CRUD module (20+ files) |
Example: Complete User Module
Step 1: Domain
Generate pure domain entities
bin/console make:hexagonal:entity user/account User
bin/console make:hexagonal:value-object user/account Email
bin/console make:hexagonal:exception user/account InvalidEmailException
Generated:
Domain/Model/User.php(pure PHP)Domain/ValueObject/Email.phpDomain/Exception/InvalidEmailException.php
Step 2: Application
Generate use cases and commands
bin/console make:hexagonal:repository user/account User
bin/console make:hexagonal:command user/account register --factory
bin/console make:hexagonal:query user/account find-by-id
Generated:
Domain/Port/UserRepositoryInterface.phpApplication/Register/RegisterCommand.phpApplication/Register/RegisterCommandHandler.phpApplication/FindById/FindByIdQuery.php
Step 3: Infrastructure
Auto-generated adapters
# Already generated with repository command!
Generated:
Infrastructure/Persistence/Doctrine/DoctrineUserRepository.phpInfrastructure/Persistence/Doctrine/Orm/Mapping/User.orm.yml
Step 4: UI
Generate controllers and forms
bin/console make:hexagonal:controller user/account RegisterUser /users/register
bin/console make:hexagonal:form user/account User
Generated:
UI/Http/Web/Controller/RegisterUserController.phpUI/Http/Web/Form/UserType.php
Architecture Layers
%%{init: {'theme':'base', 'themeVariables': { 'fontSize':'14px'}}}%%
graph TB
subgraph UI["๐ฎ UI LAYER"]
HTTP["HTTP Controllers"]
CLI["CLI Commands"]
end
subgraph APP["โ๏ธ APPLICATION LAYER"]
Commands["Commands & Queries"]
end
subgraph DOMAIN["๐ DOMAIN LAYER"]
Entities["Entities & Value Objects"]
Ports["Ports (Interfaces)"]
end
subgraph INFRA["๐ INFRASTRUCTURE LAYER"]
Adapters["Adapters (Implementations)"]
end
UI ==>|uses| APP
APP ==>|depends on| DOMAIN
INFRA -.->|implements| Ports
style DOMAIN fill:#C8E6C9,stroke:#2E7D32,stroke-width:4px
style APP fill:#B3E5FC,stroke:#0277BD,stroke-width:3px
style INFRA fill:#F8BBD0,stroke:#C2185B,stroke-width:3px
style UI fill:#E1BEE7,stroke:#6A1B9A,stroke-width:3px
Dependency Rule: All dependencies point inward. Domain has zero dependencies.
CRUD in 1 Command โก
Generate complete CRUD module with all layers:
bin/console make:hexagonal:crud blog/post Post --with-tests --with-id-vo
Generated (30+ files):
- Entity + ValueObjects + Repository
- 5 Use Cases (Create, Update, Delete, Get, List)
- 5 Controllers + Form
- All tests (Use Case + Controller)
- Doctrine YAML mapping
Documentation
Core Guides
| Guide | Description |
|---|---|
| Quick Start | Install and generate your first module in 2 minutes |
| Maker Commands | Complete reference for all 19 maker commands |
| Architecture Guide | Deep dive into hexagonal architecture patterns |
| Why Hexagonal | Business case and technical benefits |
| SOLID Principles | How hexagonal architecture enforces SOLID |
| Examples | Real-world examples and use cases |
Advanced Topics ๐
In-depth guides covering critical aspects of hexagonal architecture:
| Guide | Description |
|---|---|
| Domain vs Application Logic | Decision guide: where to place your business logic |
| Request-Response Flow | Complete end-to-end flow with diagrams |
| Port Design Principles | How to design effective port interfaces |
| Primary vs Secondary Adapters | Understanding the two sides of the hexagon |
| CQRS: Cost-Benefit Analysis | When to use CQRS (and when to avoid it) |
| Dependency Injection Guide | Complete Symfony configuration |
| Factory Pattern Guide | Complete factory implementation |
| Error Handling Strategy | Exception handling and error management |
| Anti-Patterns & Pitfalls | Avoid common mistakes |
Requirements
- PHP 8.1+
- Symfony 6.4+ or 7.x
- Composer
Contributing
We welcome contributions! See our Contributing Guide.
License
MIT License - see LICENSE for details.
Created by Ahmed EBEN HASSINE
