Laravel:ports And Adapters

Use hexagonal architecture for external systems; define ports (interfaces) and per-provider adapters; select adapter at composition edge

jpcaparas Updated

File contents

Ports and Adapters (Hexagonal)

Abstract integrations behind stable interfaces. Keep vendor SDKs out of your domain code.

Shape

  • Port: PHP interface that expresses only what the app needs
  • Adapters: one per provider, wrapping SDK quirks
  • Selection: choose adapter via config/env/service provider

Example (email)

// Port
interface MailPort {
    public function send(string $to, string $subject, string $html): void;
}

// Adapter
final class SesMailAdapter implements MailPort {
    public function __construct(private \Aws\Ses\SesClient $ses) {}
    public function send(string $to, string $subject, string $html): void {
        // wrap SES specifics here
    }
}

// Composition (AppServiceProvider)
$this->app->singleton(MailPort::class, function () {
    return match (config('mail.driver')) {
        'ses' => new SesMailAdapter(app('aws.ses')),
        default => new SmtpMailAdapter(/* ... */),
    };
});

Tips

  • Normalize SDK data into your own types/DTOs
  • Expose only portable capabilities via the port
  • Keep adapters thin and well-tested

jpcaparas/superpowers-laravel/tree/main/skills/ports-and-adapters commit 9f95cc6d14

Frequently asked questions

npx skillmds@latest add jpcaparas/laravel-ports-and-adapters