Back to Blog
Hexagonal Architecture: Ports and Adapters
The Hexagonal Concept
Hexagonal architecture (ports and adapters) isolates your core domain from external concerns. The domain defines ports (interfaces), and adapters implement these ports for specific technologies.
Structure
app/
├── Domain/
│ ├── Orders/
│ │ ├── Order.php
│ │ ├── OrderRepository.php (port)
│ │ └── PaymentGateway.php (port)
├── Application/
│ ├── Orders/
│ │ └── PlaceOrderUseCase.php
├── Infrastructure/
│ ├── Persistence/
│ │ └── EloquentOrderRepository.php (adapter)
│ ├── Payment/
│ │ └── StripePaymentGateway.php (adapter)
│ └── Http/
│ └── OrderController.php (adapter)
Ports (Interfaces)
// Domain port - no framework dependencies
namespace App\Domain\Orders;
interface OrderRepository
{
public function find(OrderId $id): ?Order;
public function save(Order $order): void;
}
interface PaymentGateway
{
public function charge(Money $amount, PaymentMethod $method): PaymentResult;
}
Adapters
// Infrastructure adapter
namespace App\Infrastructure\Persistence;
class EloquentOrderRepository implements OrderRepository
{
public function find(OrderId $id): ?Order
{
$model = OrderModel::find($id->value());
return $model ? $this->toDomain($model) : null;
}
}
// HTTP adapter
namespace App\Infrastructure\Http;
class OrderController
{
public function store(Request $request, PlaceOrderUseCase $useCase): Response
{
$result = $useCase->execute(new PlaceOrderCommand(
$request->input('customer_id'),
$request->input('items')
));
return response()->json($result);
}
}
Testing Benefits
class PlaceOrderTest extends TestCase
{
public function test_places_order(): void
{
// Use in-memory adapters for testing
$orders = new InMemoryOrderRepository();
$payments = new FakePaymentGateway();
$useCase = new PlaceOrderUseCase($orders, $payments);
$result = $useCase->execute($this->command);
$this->assertTrue($result->success);
}
}
Conclusion
Hexagonal architecture creates a clean separation between domain logic and infrastructure. Your core domain becomes framework-agnostic and highly testable.
Related Articles
Need Help With Your Project?
I respond to all inquiries within 24 hours. Let's discuss how I can help build your production-ready system.
Get In Touch