A lot of code follows the same pattern: open something, use it, then close it, even when an error happens along the way. Files and database transactions are the usual examples. This RFC from Larry Garfield and Arnaud Le Blanc borrows context managers from Python to handle that pattern for you, adding a using keyword and a ContextManager interface.

Here's safe file handling today:

$fp = fopen('file.txt', 'w');
if ($fp) {
    try {
        foreach ($someThing as $value) {
          fwrite($fp, serialize($value));
        }
    } catch (\Exception $e) {
        log('The file failed.');
    } finally {
        fclose($fp);
    }
}
unset($fp);

And here's the same thing with a context manager:

using (file_for_write('file.txt') => $fp) {
    foreach ($someThing as $value) {
        fwrite($fp, serialize($value));
    }
}
// At this point, we're guaranteed that $fp has closed, whether there was an error or not.

How it works

A context manager is an object with two methods:

interface ContextManager
{
    public function enterContext(): mixed;

    public function exitContext(?\Throwable $e = null): ?Throwable;
}
  • At the start of the block, PHP calls enterContext() and assigns its return value to the variable after =>. The variable is optional.
  • If the block ends normally, PHP calls exitContext() with no arguments.
  • If an exception is thrown, PHP passes it to exitContext(). Return it to rethrow, or return null to swallow it. In most cases, return $e is the right choice.
  • After the block, the variable is unset. If a variable with that name existed before the block, its old value is restored.

A using block doesn't create a new scope, so any other variables you set inside it are still there afterward.

Handy extras

  • You can list several context managers in one using, separated by commas.
  • try using (...) { } catch (...) { } wraps the block in a try for you.
  • break jumps to the end of the block and counts as a normal exit, and return works too.
  • File handles and other resources are wrapped in a context manager automatically, so using (fopen(...) => $fp) closes the file for you.

The keyword started out as with, matching Python, but changed to using because Laravel has a global with() helper function.

What it means for existing code

There's a new global ContextManager interface, so a class of your own with that name in the global namespace would clash. using becomes a semi-reserved keyword: you can't name a global function or constant using, but methods and class constants with that name are fine. Static analysis tools will need updates.

Where it stands

The RFC is in discussion. It targets PHP 8.6 and needs a two-thirds vote. It was last changed in April 2026.