Een integratie is niet langer een technisch detail wanneer de velden, foutcodes en toegangsregels ervan verschijnen in controllers, applicatieservices, modellen en bedrijfsprocessen. Op dat moment vereist het wijzigen van leverancier, het updaten van een API of het afhandelen van een extern incident wijzigingen in delen van de applicatie die dat systeem niet zouden moeten kennen.
Externe integraties in PHP isoleren betekent een duidelijke grens vastleggen: het domein drukt in zijn eigen taal uit wat het nodig heeft en een infrastructuurlaag vertaalt die behoefte naar het concrete protocol, formaat en gedrag van de leverancier. Het gaat er niet om een API achter een klasse met een andere naam te verbergen, maar om te voorkomen dat de beslissingen ervan de hele applicatie bepalen.
Wanneer een integratie de applicatie al vervuilt

De koppeling groeit doorgaans incrementeel. Een team gebruikt een API vanuit een controller om een urgente oplevering af te handelen; vervolgens hergebruikt een ander proces dezelfde client; uiteindelijk worden antwoord-arrays en SDK-uitzonderingen impliciete afhankelijkheden van de bedrijfslogica.
- Gebruiksscenario's ontvangen of retourneren arrays met veldnamen van de leverancier.
- Bedrijfslogica vergelijkt externe codes, zoals
ERR_42ofPENDING_REVIEW. - Controllers, opdrachten en wachtrijtaken bouwen HTTP-verzoeken rechtstreeks op.
- De uitzonderingen van de externe SDK worden buiten de infrastructuur opgevangen.
- Een wijziging van toegangsgegevens, eindpunten of versies dwingt tot het bewerken van meerdere modules.
- Tests van het domein vereisen echte verbindingen, tokens of gesimuleerde antwoorden van de leverancier.
Deze signalen betekenen niet dat er een volledige herbouw moet worden gestart. Ze geven wel aan dat het raadzaam is de integratie op risico te prioriteren: bedrijfskritikaliteit, frequentie van wijzigingen door de leverancier, aantal interne afnemers, gevoeligheid van de gegevens en moeilijkheid om van een storing te herstellen.
Contracten definiëren vanuit de taal van de bedrijfslogica
Het interne contract, ook wel poort genoemd, moet een mogelijkheid beschrijven die de applicatie nodig heeft, geen reproductie van de catalogus met bewerkingen van een externe API. Een reserveringsapplicatie kan bijvoorbeeld nodig hebben om “een reservering aan te vragen”, “de toestand ervan op te vragen” en “deze te annuleren”. Het domein hoeft niet te weten dat een leverancier XML, OAuth, een numerieke identificatiecode of een specifieke conventie voor herhaalde pogingen gebruikt.
Een poort kan worden uitgedrukt als een PHP-interface:
interface ReservationGateway
{
public function request(ReservationRequest $request): ReservationResult;
public function status(ReservationReference $reference): ReservationStatus;
public function cancel(ReservationReference $reference): void;
}De typen van het contract moeten tot de interne taal behoren. ReservationRequest bevat de gegevens die nodig zijn voor de zakelijke beslissing; het mag geen authenticatievelden, HTTP-headers of verouderde namen van de leverancier bevatten. Op dezelfde manier kan een interne referentie de externe identiteit inkapselen zonder deze dominant te maken in alle gebruiksscenario's.
De onderdelen van een integratiegrens
Poort, adapter en interne DTO
De poort is de interface die de applicatie gebruikt. De adapter is de implementatie die met het externe systeem communiceert. Daartussen brengen interne DTO's gegevens over in een stabiele structuur voor de applicatie.
De adapter vertaalt in beide richtingen: hij zet de interne DTO om in een specifiek verzoek en normaliseert het antwoord tot een resultaat dat het domein kan interpreteren. Als de leverancier guest_count wijzigt in travellers, moet de wijziging beperkt blijven tot die adapter.
Configuratie, toegangsgegevens en transport
Eindpunten, tokens, tijdslimieten, certificaten en beleid voor herhaalde pogingen zijn infrastructuurverantwoordelijkheden. Ze moeten via configuratie worden geïnjecteerd en buiten domeinentiteiten en domeinservices blijven. Het is ook raadzaam de HTTP-client of SDK van de adapter te scheiden: dit maakt het eenvoudiger om bibliotheken te vervangen, telemetrie vast te leggen en de gegevensvertaling te testen zonder afhankelijk te zijn van het daadwerkelijke transport.
Vertaling van fouten en onzekere toestanden
Niet alle fouten worden op dezelfde manier behandeld. Een verzoek dat door de leverancier wegens een validatiefout wordt afgewezen, kan voor de gebruiker herstelbaar zijn; een authenticatiefout vereist operationele interventie; een tijdslimiet kan een onzekere toestand achterlaten omdat de leverancier het verzoek mogelijk heeft verwerkt.
Het interne contract moet deze verschillen weergeven zonder externe uitzonderingen door te laten. De adapter kan bijvoorbeeld een validatieantwoord omzetten in ReservationRejected, een tijdelijk probleem in TemporaryUnavailable en een tijdslimiet na het verzenden van het verzoek in UnknownSubmissionState. Dit laatste mag niet als een gewone fout worden behandeld: het kan een latere controle via een idempotentiesleutel of operationele afstemming vereisen.
Fouten vertalen betekent niet dat details worden verwijderd. Leg de correlatie-ID, de technische oorzaak en het relevante antwoord veilig vast, en voorkom dat geheimen of gevoelige gegevens aan de gebruiker worden blootgesteld.
Voorbeeld van inkapseling van een reserveringsservice
Stel dat een leverancier een JSON-verzoek vereist met datums in een specifiek formaat, een eigen hotelcode en een autorisatieheader. Het interne gebruiksscenario mag dat verzoek niet opbouwen. Het ontvangt een reserveringsaanvraag, past zijn regels toe en roept ReservationGateway aan.
De adapter ExternalReservationAdapter voert de specifieke taken uit:
- Zet de interne accommodatie-ID om naar de code die de leverancier herkent.
- Formatteert datums, gasten en voorkeuren volgens het externe contract.
- Voegt toegangsgegevens en een idempotentiesleutel toe.
- Interpreteert HTTP-codes, foutberichten en eigen toestanden.
- Retourneert een interne referentie en toestand.
De regel die bepaalt wanneer een reservering acceptabel is, blijft in de applicatie; de regel voor het aanvragen van die reservering bij deze leverancier blijft in de adapter. Als een tweede leverancier wordt toegevoegd, kan dezelfde poort worden geïmplementeerd, mits de bedrijfsfunctie gelijkwaardig is. Is dat niet zo, dan kan het forceren van een gemeenschappelijke interface belangrijke verschillen verbergen en dubbelzinnige beslissingen creëren.
Een al gekoppelde integratie extraheren
Een veilige migratie vereist niet dat de productevolutie wordt stilgelegd. Begin met een inventaris: lokaliseer directe aanroepen, SDK-klassen, externe formaten, doorgelaten uitzonderingen en afnemers. Identificeer eerst de kritieke paden of de paden die het vaakst wijzigen.
- Introduceer een façade: creëer de poort en een initiële adapter die tijdelijk delen van de bestaande client kan hergebruiken.
- Migreer afnemers per proces: vervang de directe aanroepen van één gebruiksscenario tegelijk. Vermijd dat er twee verschillende interpretaties van dezelfde fout blijven bestaan.
- Centraliseer de gegevensvertaling: verwijder conversies van externe velden en codes uit controllers, services en sjablonen.
- Voeg observatiemogelijkheden toe: registreer vertraging, resultaten, genormaliseerde fouten en correlatie tussen het interne verzoek en de externe aanroep.
- Verwijder directe toegang: beperk of verwijder de blootgestelde client wanneer er geen afnemers meer zijn, om regressies te voorkomen.
Tijdens de transitie mag de façade niet veranderen in een generieke container voor SDK-methoden. Het doel ervan is een nuttige en stabiele grens te definiëren, niet de koppeling naar een andere map te verplaatsen.
Tests en criteria om de isolatie te valideren
Tests van het domein moeten testdubbels van de poort gebruiken. Zo verifiëren ze zakelijke beslissingen zonder netwerk, toegangsgegevens of toevallig gedrag van de leverancier. Tests van de adapter moeten daarentegen de gegevensvertaling van verzoeken, antwoorden en fouten controleren tegen een gecontroleerde omgeving, een gesimuleerde server of contracten die door het externe systeem zijn gedocumenteerd.
Het resultaat is verifieerbaar als aan deze criteria wordt voldaan:
- Een wijziging van formaat, eindpunt of SDK blijft geconcentreerd in de adapter en de configuratie ervan.
- Gebruiksscenario's zijn afhankelijk van interne contracten, niet van HTTP-clients of externe typen.
- Uitzonderingen en codes van de leverancier overschrijden de grens niet.
- Onzekere toestanden hebben een expliciete behandeling, inclusief idempotentie of latere controle wanneer dat nodig is.
- Tests van de bedrijfslogica draaien met testdubbels en integratietests valideren de daadwerkelijke vertaling.
Veelgemaakte fouten voordat een andere leverancier wordt toegevoegd

Voortijdige abstractie is een risico: creëer geen complexe hiërarchie voor één stabiele integratie zonder werkelijke vervangingsbehoeften. Ook het andere uiterste faalt: de volledige externe API repliceren in een interne interface zorgt ervoor dat het domein de complexiteit ervan overneemt.
Bevestig vóór de integratie welke mogelijkheid de bedrijfslogica nodig heeft, wie eigenaar is van elk gegeven, bij welke fouten actie mogelijk is, hoe duplicatie van bewerkingen wordt voorkomen en wat er gebeurt als er geen antwoord komt. Definieer de poort op basis van die beslissingen, implementeer de adapter als vertaler en houd externe bijzonderheden aan de rand. Die discipline maakt het mogelijk externe integraties in PHP te isoleren zonder dat iedere leverancierswijziging uitgroeit tot een wijziging die dwars door de applicatie heen loopt.



