Re: [RFC] Context Managers
| From: | Tim Düsterhus | Date: | Sun, 18 Jan 2026 13:07:02 +0000 |
| Subject: | Re: [RFC] Context Managers | ||
| References: | 1 2 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-129780@lists.php.net to get a copy of this message | ||
Hi
On 1/15/26 19:38, Volker Dusch wrote:
a function is already a reasonable scopeThat - together with the other points you raised - made me realize one thing: In contrast to block scoping, the main purpose of “Context Managers” is *not* managing arbitrary variables in the current scope in combination with existing control structures. Instead it is just managing a single variable in a reasonably *self-contained* fashion, with other variables just needing to “exist”. It could therefore also just be a regular function taking a callback, as is already done in userland, e.g. with Laravel's DB::transaction() helper. I believe something like this would be equivalent to the RFC:
function using(
callable $runInContext,
ContextManager ...$managers
): void {
$contexts = [];
foreach ($managers as $manager) {
$contexts[] = $manager->enterContext();
}
try {
$runInContext(...$contexts);
foreach (array_reverse($managers) as $manager) {
$manager->exitContext();
}
} catch (Throwable $e) {
foreach (array_reverse($managers) as $manager) {
if ($manager->exitContext($e) === true) {
$e = null;
}
}
if ($e !== null) {
throw $e;
}
}
}
This would completely side-steps the “break to exit” question, since a return will just work. It also avoids introducing new keywords, it just requires a new function in the global namespace.
I understand that using variables from the current scope in a Closure is currently not particularly convenient, particularly when they need to be changed. However this is something that can be solved in a generic fashion, for example inspired by the C++ lambda syntax:
// Captures everything by value and $result by reference.
function ($context) use (*, &$result) { }
// Captures everything by reference.
function ($context) use (&*) { }
which would also be useful in other situations.
Best regards
Tim Düsterhus