Symfony-hexagonal-skill symfony-ports-adapters
Symfony ports and adapters — port interfaces, adapter implementations, dependency injection, autowiring, repository interfaces. Triggers on: port, adapter, interface, repository interface, DI, autowiring, dependency injection, services.yaml, binding
install
source · Clone the upstream repo
git clone https://github.com/aligundogdu/symfony-hexagonal-skill
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/aligundogdu/symfony-hexagonal-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/symfony-ports-adapters" ~/.claude/skills/aligundogdu-symfony-hexagonal-skill-symfony-ports-adapters && rm -rf "$T"
manifest:
skills/symfony-ports-adapters/SKILL.mdsource content
Symfony Ports & Adapters
You are an expert in the Ports & Adapters pattern within Symfony hexagonal architecture.
When to Activate
- User needs to define a port (interface) for external dependency
- User needs to implement an adapter
- User asks about DI configuration or autowiring
- User wants to bind an interface to a concrete implementation
Port = Interface in Domain
Ports are interfaces that define contracts for external dependencies. They live in
Domain/{Module}/Port/.
Rules
- One interface per concern (Single Responsibility)
- Domain-centric naming (not tech-centric):
notUserRepositoryInterfaceDoctrineUserRepository - Only domain types in signatures (value objects, entities, primitives)
- No framework types in port signatures
Common Port Types
| Port Type | Example |
|---|---|
| Repository | |
| External Service | |
| Notification | |
| File Storage | |
| Event Dispatcher | |
Template
namespace App\Domain\{Module}\Port; interface {Concern}Interface { public function methodUsingDomainTypes(ValueObject $param): ?Entity; }
Adapter = Implementation in Infrastructure
Adapters implement ports using specific technologies. They live in
Infrastructure/{Module}/.
Rules
- Implements exactly one port interface
- Contains ALL technology-specific code
- Named with technology prefix:
,Doctrine{Entity}RepositoryStripe{Payment}Gateway
when possiblefinal readonly class
Template
namespace App\Infrastructure\{Module}\Persistence; use App\Domain\{Module}\Port\{Repository}Interface; final readonly class Doctrine{Entity}Repository implements {Repository}Interface { public function __construct( private EntityManagerInterface $entityManager, ) { } // implement all port methods }
DI Configuration
# config/services.yaml services: # Bind ports to adapters App\Domain\User\Port\UserRepositoryInterface: alias: App\Infrastructure\User\Persistence\DoctrineUserRepository App\Domain\Payment\Port\PaymentGatewayInterface: alias: App\Infrastructure\Payment\ExternalService\StripePaymentGateway App\Domain\Notification\Port\NotificationServiceInterface: alias: App\Infrastructure\Notification\ExternalService\SymfonyMailerAdapter
References
See
references/ for detailed guides:
— Full examples for various port typesport-adapter-examples.md
— Advanced DI configuration patternsdi-configuration.md