# 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

- Skill: `aligundogdu/symfony-ports-adapters` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add aligundogdu/symfony-ports-adapters`
- Raw SKILL.md: https://api.skillmd.com/api/skills/aligundogdu/symfony-ports-adapters/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: aligundogdu (https://skillmd.com/u/aligundogdu)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/aligundogdu/symfony-ports-adapters

---


# 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): `UserRepositoryInterface` not `DoctrineUserRepository`
- Only domain types in signatures (value objects, entities, primitives)
- No framework types in port signatures

### Common Port Types

| Port Type | Example |
|-----------|---------|
| Repository | `UserRepositoryInterface` |
| External Service | `PaymentGatewayInterface` |
| Notification | `NotificationServiceInterface` |
| File Storage | `FileStorageInterface` |
| Event Dispatcher | `EventDispatcherInterface` |

### Template
```php
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}Repository`, `Stripe{Payment}Gateway`
- `final readonly class` when possible

### Template
```php
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

```yaml
# 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:
- `port-adapter-examples.md` — Full examples for various port types
- `di-configuration.md` — Advanced DI configuration patterns

