response()->acmeFailure(...) toevoegen zonder dat controllers van een basisklasse hoeven te erven.
Deze pagina is gebaseerd op de officiële Laravel-documentatie op de standaardbranch 13.x en de officiële implementatie van de nieuwste Framework-release v13.40.0, gecontroleerd op 8 november 2026. Voortbouwend op de basis van Responses en de Macroable-trait behandelt ze de grenzen waar je rekening mee moet houden wanneer je een macro onderhoudt als publieke API van een gedistribueerd package.
Registreer op de Factory, niet op de response
De naamResponse verwijst zowel naar een facade die vraagt om een response op te bouwen als naar de klasse van de gegenereerde HTTP-response. Wat Response::macro() in de officiële documentatie uitbreidt, is ResponseFactory, de klasse waarnaar de facade wordt opgelost.
response() zonder argumenten geeft de Factory terug. response('inhoud') en response(null) geven daarentegen een met make() gemaakte response terug, dus ze roepen niet hetzelfde doel aan.
Een opbouw-API voor fout-JSON publiceren
Registreren in een service provider
Registreer in de methodeboot() van src/HttpServiceProvider.php een macro met een packageprefix. Hoe de provider wordt geladen, lees je in Package discovery.
Het publieke contract in dit voorbeeld is JSON met error.code en error.message, plus een HTTP-status tussen 400 en 599. Deze statusbeperking is geen beperking van het macromechanisme van Laravel. Het package legt haar vast voor een API die alleen voor fouten bedoeld is.
runningInConsole()-voorwaarde. Ook HTTP-featuretests draaien vanuit de CLI.
Een provider die alleen deze registratie verzorgt, hoeft ook geen uitgestelde provider te zijn die wacht tot een service wordt opgelost. Hoe uitgestelde registratie werkt, lees je in Uitgestelde service providers.
Aanroepen vanuit een controller
Nadat je bedrijfslogica een conflict heeft vastgesteld, geef je de gekozen foutcode en een bericht voor de gebruiker door.409 en de JSON ziet er als volgt uit. Net als bij een gewone json() is de Content-Type application/json.
De macro bouwt alleen de responses op waar je hem aanroept. Hij zet validatie-exceptions of authenticatiefouten niet automatisch om naar dit formaat. Hij voegt ook geen omschakeling tussen HTML en JSON toe op basis van de
Accept-header.$this in de Closure en het aanroeppad
De Factory gebruikt Macroable. Wanneer je een niet-gedefinieerde methode op een instantie aanroept, zoekt __call() de geregistreerde macro op en bindt een gewone Closure opnieuw aan de instantie waarop hij werd aangeroepen.
Ook al staat de registratiecode in een methode van de service provider, $this is tijdens het uitvoeren de Factory en niet de service provider. Daarom roept $this->json() in het voorbeeld de gewone methode van de Factory aan.
- Definieer macro’s die
$thisgebruiken met een gewonefunction (...) { ... }. Eenstatic functionheeft geen instantie-$this. - Als je een invokable object registreert, wordt het niet opnieuw gebonden zoals een Closure. Laat dat object zelf de benodigde afhankelijkheden ontvangen, bijvoorbeeld via de eigen constructor.
- De argumenten van de macro zijn de argumenten die de aanroeper doorgeeft. Ook als je
Requestof iets dergelijks als type opgeeft, injecteert Macroable het niet automatisch vanuit de container.
Response::acmeFailure() lijkt statisch, maar wordt intern doorgestuurd naar de Factory-instantie. Illuminate\Routing\ResponseFactory::acmeFailure() op de concrete klasse is daarentegen een echte statische aanroep, en __callStatic() bindt de Closure zonder instantie. Een macro zoals deze, die $this->json() gebruikt, ondersteunt geen statische aanroepen op de concrete klasse.
Naamconflicten behandelen als compatibiliteitsprobleem
macro() wijst alleen een waarde toe in een statische array met de naam als sleutel. Het registreren van een bestaande naam geeft geen waarschuwing.
Kies liever een naam die je package herkenbaar maakt, zoals
acmeFailure, dan een algemene naam zoals failure. Controleer bij Laravel-updates ook op conflicten met echte methoden met method_exists(ResponseFactory::class, 'acmeFailure').
Als je hasMacro() controleert en de registratie onvoorwaardelijk overslaat, gebruik je mogelijk de implementatie van een ander package alsof het je eigen API is. Alleen wanneer je “de applicatie kan hem overschrijven door eerder te registreren” onderdeel van de specificatie maakt, publiceer je die voorrang samen met de vereiste argumenten en retourwaarde. Het voorbeeld hierboven volgt het beleid om bij elke start van de provider de eigen definitie van het package te registreren.
Registratiestatus en levensduur van de response scheiden
Het macroregister is een statische eigenschap van de Factory. De Factory opnieuw aanmaken of de opgeloste facade-instantie wissen maakt dit register niet leeg. Ook in tests die de applicatie binnen hetzelfde PHP-proces opnieuw aanmaken, kan de registratiestatus blijven bestaan. De voorbeeldmacro laatjson() daarentegen bij elke aanroep een nieuwe JsonResponse aanmaken. Wat gedeeld wordt, is de opbouwlogica, niet de inhoud of headers van de response zelf.
Dit zijn de grenzen die je in langlopende workers moet respecteren.
- Leg bij de registratie niet de huidige Request, de geauthenticeerde gebruiker of de tenant vast met
use (...). Geef deze waarden bij de aanroep als argumenten door. - Hergebruik geen response die bij de registratie is aangemaakt. Geef elke keer een nieuwe response terug.
- Als je configuratie bij de registratie als waarde vastlegt, neem dan in de specificatie op dat die waarde binnen het proces behouden blijft.
- Herstart na een package-update langlopende processen zodat de nieuwe registratiecode wordt toegepast.
Het HTTP-contract testen met echte retourwaarden
Plaats in een Laravel 13-testapplicatie die het package via Composer kan laden het volgendetests/Feature/ResponseMacroTest.php. Voor Tests\TestCase en de basis van HTTP-tests, zie HTTP-tests. Voor het opzetten van een zelfstandige packageomgeving, zie Packages testen.
Response::shouldReceive('acmeFailure'), worden de macroregistratie, de Closure-binding en het genereren van JSON niet uitgevoerd. Houd controles op het aantal aanroepen gescheiden en controleer zoals hierboven de echte HTTP-response.
Behandel daarnaast de inhoud, status en headers die gebruikers ontvangen als onderdeel van de compatibiliteit.
- Houd
error.codestabiel voor machinale controles en onderscheid het van wijzigingen in het weergegeven bericht. - Argumentnamen worden gebruikt als benoemde argumenten, dus controleer de impact van een wijziging net als bij standaardwaarden of volgorde.
- Geef responses zonder inhoud, zoals
204, terug met een andere API zoalsnoContent(), niet als fout-JSON. - Als je extensies toestaat die de
Content-Typevia eigen headers wijzigen, houd die dan consistent met het formaat van de inhoud. - Als je doel dataserialisatie of paginering is, overweeg dan ook Eloquent API-resources in plaats van ze alleen met macro’s opnieuw te implementeren.
Checklist voor langetermijnonderhoud
- Op de ondersteunde Laravel 13-combinaties start de provider op en is de macro aan te roepen via zowel de helper als de facade.
- De macronaam conflicteert niet met andere registraties of met echte methoden van de Factory.
- De compatibiliteit van JSON-sleutels, HTTP-status, headers, standaardwaarden en benoemde argumenten wordt getest.
- Opeenvolgende aanroepen delen geen responses, en bij de registratie wordt geen Request- of gebruikersinformatie bewaard.
- Tests die registraties resetten, zijn geïsoleerd van andere packages.
- Het herstarten van langlopende processen maakt deel uit van de updateprocedure.
Geraadpleegde primaire bronnen
- Officiële Laravel-documentatie: Response macros en JSON responses (13.x)
- Officiële Laravel-documentatie: Package development (13.x)
- De Response-facade en waarnaar die wordt opgelost (v13.40.0)
- Doorsturen van de Facade naar de instantie (v13.40.0)
- De helper response() (v13.40.0)
- Opbouwlogica van ResponseFactory (v13.40.0)
- Registratie, binding en reset in Macroable (v13.40.0)
- Officiële tests van Macroable (v13.40.0)