Skip to main content
Om een package niet alleen bij gewone HTTP-requests maar ook in Octane en queue workers bruikbaar te maken, moet je bepalen hoe lang een service wat mag vasthouden. Als je data per request in een singleton opslaat, kan een andere verwerking verouderde data te zien krijgen. Op deze pagina bekijken we de implementatie van de container, de queue worker en Octane in Laravel Framework v13.36.0, en verbinden we de basisregistratiemethoden van de service container met het langetermijnonderhoud van packages. Alleen scoped() kiezen betekent niet dat alle verwijzingen tussen objecten en alle statische state worden gereset.

Kies de registratiemethode op basis van de levensduur van de service

Deze tabel vergelijkt normale resoluties. Controleer speciale paden, zoals resolutie met expliciete parameters of contextual binding, apart. Ook bij bind() blijft de verwijzing bestaan als je de opgehaalde service opslaat in een property van een andere singleton. De registratiemethode is een regel van de container voor het aanmaken en hergebruiken, geen regel die objecten die de gebruiker vasthoudt geforceerd opnieuw aanmaakt.

scoped combineert gedeelde registratie met het bijhouden van te verwijderen sleutels

De onderzochte Container::scoped() doet de volgende twee dingen:
  1. De registratiesleutel vastleggen in scopedInstances.
  2. singleton() aanroepen en registreren als gedeelde binding.
De instantie zelf wordt, net als bij een singleton, opgeslagen in instances. forgetScopedInstances() voert unset() uit op de opgeslagen instanties voor de vastgelegde sleutels. Omdat de aanmaaklogica van de binding blijft bestaan, kan bij de volgende normale resolutie een nieuw object worden aangemaakt. Dit proces initialiseert geen properties van het oude object en herschrijft geen verwijzingen die andere objecten vasthouden. Een oud object waarnaar nog een verwijzing bestaat, kan nog steeds worden gebruikt.

De uitvoeringsomgeving maakt de grens

De container zelf houdt niet in de gaten wanneer een HTTP-request of job begint.
  • Queue worker: QueueServiceProvider geeft een callback die de scope reset door aan de Worker. Worker::daemon() roept deze aan in de lus voordat de volgende job wordt opgehaald, en binnen de callback worden onder andere forgetScopedInstances() en het wissen van de geresolvede instanties van Facades uitgevoerd.
  • Octane: De officiële standaardconfiguratie registreert FlushTemporaryContainerInstances bij OperationTerminated. Deze listener roept forgetScopedInstances() aan.
  • Eigen langlopende commando’s of lussen: Simpelweg herhaaldelijk make() aanroepen vormt geen grens. De levenscyclus moet aan de kant van het uitvoeringsplatform worden ontworpen.
Roep forgetScopedInstances() niet op eigen initiatief aan vanuit gewone applicatielogica of vanuit boot() van een package. Dit beïnvloedt alle scoped services in de hele container. Bovendien doorlopen niet alle jobpaden, inclusief synchrone uitvoering, noodzakelijkerwijs hetzelfde resetpad als een langlopende Worker.

Maak state die binnen een verwerking wordt gedeeld scoped

Neem als voorbeeld een bezorgpackage dat binnen één request of job de identifier van de bestemming wil delen. In plaats van de HTTP-Request direct vast te houden, slaan we alleen de benodigde waarde op.
In de service provider van het package registreer je een lege context, zonder bij het aanmaken de state van de gebruiker te lezen.
In een controller of in handle() van een job in de gebruikende applicatie stel je de identifier in nadat de invoer is gevalideerd en de rechten zijn gecontroleerd. Andere services die dit type binnen dezelfde levenscyclus resolven, zien dezelfde context.
Deze context is geen autorisatiemechanisme. Dat een identifier kan worden ingesteld, betekent nog niet dat toegang tot die bestemming is toegestaan. Bovendien is scoped() geen persistentie naar een database of externe cache. Waarden die aan de volgende job moeten worden doorgegeven, geef je expliciet mee als jobdata.
In Octane worden register() en boot() van service providers uitgevoerd bij de initiële start van de worker. Ontwerp niet zo dat de huidige gebruiker of bestemming in boot() in de context wordt opgeslagen. Stel waarden per verwerking pas in nadat de verwerking is begonnen.

Verwijzingen van een singleton naar scoped worden niet automatisch bijgewerkt

Bij de volgende registratie werkt het niet zoals bedoeld als je alleen de context scoped maakt.
Als DeliveryService de context in de constructor in een property opslaat, blijft hij de eerst aangemaakte context vasthouden. Ook als de opgeslagen context uit de container wordt verwijderd, veranderen de properties van de al aangemaakte DeliveryService niet. Kies een oplossing die past bij de verantwoordelijkheid van de service.
  1. Geef de per verwerking benodigde waarden mee als methodeargumenten. Als er geen state gedeeld hoeft te worden, is dit het eenvoudigst.
  2. Maak ook de vasthoudende kant scoped. Zowel DeliveryService als de context worden per verwerking opnieuw aangemaakt.
  3. Geef een resolver mee die bij gebruik resolvet. Als de singleton behouden moet blijven, haal je de benodigde service telkens op uit de huidige container.
In het derde voorbeeld wordt de oude context niet in de closure ingesloten, maar wordt hij op het moment van aanroepen geresolved.
De DeliveryService in dit voorbeeld moet worden aangepast zodat hij in de constructor een Closure ontvangt en een API wordt die deze bij elke bewerking aanroept. Als je de resolver in de constructor maar één keer aanroept en het resultaat opslaat, is het probleem niet opgelost. Dit is een ontwerpvoorbeeld waarbij de container resolver uit de officiële Octane-documentatie wordt toegepast op een packagespecifieke context.

Controleer ook state die scoped niet wist

scoped() verwijdert de volgende state niet automatisch:
  • Waarden die zijn toegevoegd aan eigen statische properties van het package
  • Verwijzingen naar de context die zijn opgeslagen in een andere singleton of in globale variabelen
  • Een “huidige gebruiker” of “huidige bestemming” die in een singleton wordt vastgehouden
  • Verwijzingen die worden vastgehouden door eigen Facades of cachelagen
Maak onderscheid tussen resets door het standaard uitvoeringsplatform en resets van packagespecifieke state. Het aantal plekken waar state per verwerking wordt vastgehouden verminderen is eenvoudiger dan in elke uitvoeringsomgeving eigen wislogica te onderhouden.

Schrijf tests die grenzen overschrijden binnen dezelfde container

Als HTTP-tests alleen elke keer een nieuwe applicatie aanmaken, kun je problemen missen waarbij een langlopend proces dezelfde container blijft gebruiken. Controleer eerst op containerniveau het delen binnen dezelfde verwerking en het opnieuw aanmaken na de grens. De volgende tests zijn in PHPUnit-formaat. De eerste test gebruikt, net als de officiële Container-tests, forgetScopedInstances() en controleert het effect van de grens zonder de hele Worker te starten.
De tweede test legt het gedrag vast dat verwijzingen blijven bestaan. Voeg aan je echte package ook tests toe die controleren dat met de gekozen oplossing een nieuwe context of nieuwe waarde wordt gebruikt. Unittests op containerniveau verifiëren niet het werkelijke uitvoeringspad van de Octane-sandbox of de queue worker. Je hebt ook integratietests nodig die opeenvolgende verwerkingen uitvoeren in de uitvoeringsomgevingen waarvoor je ondersteuning claimt. Bij deploys die de registratiemethode of de service-implementatie wijzigen, herlaad je de langlopende processen om de nieuwe code toe te passen.

Gerelateerde pagina’s

Hooks na het resolven van packageservices

Bekijk afterResolving, het ophalen van gedeelde instanties en de verschillen in configuratie bij herhaalde resolutie.

Laravel Octane

Bekijk aandachtspunten voor het vasthouden van de Request en de container, en voor het beheer van langlopende processen.

Geraadpleegde primaire bronnen

Laatst gewijzigd op 14 oktober 2026