{
    "slug": "ports_adapters_php",
    "term": "Ports & Adapters (PHP Worked Example)",
    "category": "architecture",
    "difficulty": "advanced",
    "short": "Hexagonal Architecture in PHP — the application core exposes ports (interfaces), and adapters implement them for HTTP, CLI, databases, and external services.",
    "long": "Ports & Adapters (Alistair Cockburn, 2005) defines the application as a hexagon with ports on each face. Input ports are interfaces the application offers (CreateOrderUseCase, FindUserQuery). Output ports are interfaces the application requires (OrderRepository, EmailGateway). Adapters implement ports for specific technologies: HttpAdapter drives input ports; DoctrineAdapter implements output ports. The core never depends on adapters — the dependency always points inward. This enables testing the core without any infrastructure, and swapping adapters without touching the core.",
    "aliases": [
        "hexagonal architecture PHP",
        "ports and adapters",
        "Alistair Cockburn"
    ],
    "tags": [
        "architecture",
        "php",
        "ddd",
        "testing"
    ],
    "misconception": "Ports & Adapters requires a complex folder structure — the pattern is about dependency direction, not folder layout; a simple PHP project can implement it with just interfaces and implementations in any structure.",
    "why_it_matters": "A PHP application where controllers call Eloquent models directly cannot be tested without a database — ports & adapters makes the entire application core testable with pure PHP, no infrastructure needed.",
    "common_mistakes": [
        "Output port interface in the infrastructure layer — interfaces belong to the application core.",
        "Application core importing Doctrine or Eloquent classes — the core must not know about adapters.",
        "One port per use case — keep ports focused; CreateOrderPort not a generic OrderPort with 20 methods.",
        "Not testing through ports — tests should call use cases via ports, not internal methods."
    ],
    "when_to_use": [],
    "avoid_when": [],
    "related": [
        "hexagonal_architecture",
        "clean_architecture",
        "dependency_injection",
        "repository_pattern"
    ],
    "prerequisites": [
        "hexagonal_architecture",
        "dependency_inversion",
        "clean_architecture"
    ],
    "refs": [
        "https://alistair.cockburn.us/hexagonal-architecture/"
    ],
    "bad_code": "// Core directly depends on infrastructure — tightly coupled:\nclass CreateOrderUseCase {\n    public function __construct(\n        private \\Doctrine\\ORM\\EntityManager $em, // Infrastructure in core!\n        private \\Swift_Mailer $mailer,            // Infrastructure in core!\n    ) {}\n    // Cannot test without Doctrine and Swift\n}",
    "good_code": "// Core depends only on own interfaces (ports):\ninterface OrderRepository {   // Output port — in core\n    public function save(Order $order): void;\n}\ninterface EmailGateway {       // Output port — in core\n    public function sendConfirmation(Order $order): void;\n}\n\nclass CreateOrderUseCase {     // Core — no infrastructure imports\n    public function __construct(\n        private OrderRepository $orders,   // Port — not Doctrine\n        private EmailGateway    $email,    // Port — not SwiftMailer\n    ) {}\n}\n\n// Adapters in infrastructure layer:\nclass DoctrineOrderRepository implements OrderRepository { /* ... */ }\nclass SwiftEmailGateway        implements EmailGateway    { /* ... */ }\n// Tests inject InMemoryOrderRepository — no DB needed",
    "quick_fix": "Define ports (interfaces) in your domain/application layer — adapters implement them in the infrastructure layer; the domain never imports from infrastructure, only infrastructure imports from domain",
    "severity": "info",
    "effort": "high",
    "created": "2026-03-16",
    "updated": "2026-03-22",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/ports_adapters_php",
        "html_url": "https://codeclaritylab.com/glossary/ports_adapters_php",
        "json_url": "https://codeclaritylab.com/glossary/ports_adapters_php.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[Ports & Adapters (PHP Worked Example)](https://codeclaritylab.com/glossary/ports_adapters_php) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/ports_adapters_php"
            }
        }
    }
}