Understand whether a PHP closure captures a value or a reference
A callback is created while a retry counter is zero. The counter is incremented later, but the callback still reports zero. A use ($counter) capture took the value at creation time.
Choose the intended lifetime
<?php
$counter = 0;
$snapshot = function () use ($counter) { return $counter; };
$current = function () use (&$counter) { return $counter; };
$counter = 3;
assert($snapshot() === 0);
assert($current() === 3);
A reference capture reads the shared variable. That can be useful for a small local accumulator, but it creates coupling between the callback and later assignments. A value capture is often easier to reason about when a callback should represent a fixed decision.
Objects add another distinction
Capturing an object by value does not make a deep copy of that object's properties. Mutations to the same object can still be observed. If a task needs a stable snapshot, construct an immutable value containing only the required fields.
For queued work, do not assume a closure can retain a live request's entire environment. Framework serialization, job boundaries, and database reloading change what survives. Prefer explicit job data for background processing.
Test a callback before and after the outer variable changes. For object inputs, also test property mutation and replacement with a different object. Those are separate cases. Keep captured variables few and well named; a callback that silently depends on a large mutable scope is difficult to retry, isolate, or move into a background job later.
Reference
Official documentation. The examples here illustrate the stated boundary; adapt them to your application and test its failure paths.