The Adapter pattern protects your PHP application from third-party APIs by translating external clients into internal contracts.
External APIs change shape
Third-party services rarely match the language of your application. A payment provider has its own request format, error codes, retries, and response objects. If that provider leaks across your codebase, switching providers or testing workflows becomes painful. The Adapter pattern creates a local interface and translates between your application and the external API.
Design the internal contract first
Start with what your application needs. A PaymentGateway interface might define charge, refund, and retrievePayment. It should use your own value objects and exceptions. The StripePaymentGateway adapter can translate those calls into Stripe requests. If another provider is added later, it implements the same local contract.
Contain provider language
Provider-specific names should stay inside the adapter. The rest of the application should not know about a provider status string or response class. Convert external data into internal DTOs or value objects. Convert provider errors into application exceptions. This keeps the domain clean and predictable.
Testing without network calls
Adapters make tests faster. Application services can use a fake PaymentGateway without calling the network. Adapter tests can be fewer and more focused, using mocked HTTP responses or provider sandbox tests. This prevents every checkout test from depending on external availability.
Retries, logging, and observability
Adapters are a good place for provider-specific retry logic and structured logging. They know the external boundary. Still, avoid hiding too much. Important failures should be visible to the application through clear exceptions or result objects so workflows can decide whether to retry, notify, or stop.
Adapter vs facade
An adapter changes one interface into another. A facade provides a simplified entry point to a subsystem. Laravel facades are a framework convenience and not the same thing as the GoF Facade pattern. The article on facades explains that distinction in detail.
Where it fits
Any dependency outside your control is a candidate for an adapter: payment providers, email APIs, AI services, search engines, analytics tools, and storage services.
Internal reading path
This article is part of a connected OOP and design patterns series. Continue with these related guides:
- Dependency Injection in Laravel: Writing Flexible Services
- Facade Pattern vs Laravel Facades: Understanding the Difference
- Repository Pattern in Laravel: When It Helps and When It Hurts
Practical checklist
- Name the responsibility before choosing a pattern.
- Prefer small contracts where behavior varies or external services are involved.
- Keep controllers at the edge and move workflows into named application code.
- Add tests around the behavior that is most likely to change.
- Use patterns to reduce coupling, not to make simple code look advanced.