phplang/scope-exit
Tiny PHP helper that emulates “defer”/scope-exit behavior: register callbacks to run automatically when a block/function ends, ensuring reliable cleanup (close files, unlock mutexes, rollback temp state) even if exceptions occur.
Use the scope_exit() helper to register cleanup logic that runs automatically when the current scope exits — even on exceptions. Start by installing (if available via Composer), then wrap resource management with a closure:
$lock = acquireLock('task');
scope_exit(fn() => releaseLock($lock));
// ... critical section ...
Your first real use case: managing temporary files, streams, or locks without sprawling try/finally. Read README.md if present, but expect sparse docs — the API is minimal (just one function).
$resource = fopen('php://temp', 'r+');
scope_exit(fn() => fclose($resource));
fwrite($resource, 'data');
DB::beginTransaction();
$committed = false;
scope_exit(fn() => $committed ? : DB::rollBack());
// ... operations ...
DB::commit();
$committed = true; // prevents rollback on exit
$startTime = hrtime(true);
scope_exit(fn() => logger()->debug('Operation took ' . (hrtime(true) - $startTime)/1e6 . ' ms'));
// ... work ...
$originalEnv = $_ENV;
scope_exit(fn() => $_ENV = $originalEnv);
putenv('TEST_MODE=1');
// ... assertions ...
use ($value) to capture by value — otherwise, changes before scope exit may affect your cleanup:
$x = 1;
scope_exit(fn() => echo $x); // prints 2 if $x is changed later
$x = 2;
try/catch for critical operations:
scope_exit(fn() => {
try { cleanup(); } catch (\Throwable $e) { /* log & ignore */ }
});
cancel(), use a mutable flag (e.g., &$skip = false):
$skipCleanup = false;
scope_exit(fn() => $skipCleanup ?: $this->deleteTempFile());
// ... on success ...
$skipCleanup = true;
scope_exit(). Add explicit callable type hints or PHPDoc to avoid IDE errors.How can I help you explore Laravel packages today?