# Examples comparing Block Scoped RAII and Context Managers

- Thread: https://externals.io/message/129271
- Original archive: https://news-web.php.net/php.internals/129271
- Started by Frederik Bosch on 2025-11-16T15:29:35+00:00
- Messages: 1
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #129271 — Frederik Bosch — 2025-11-16T15:29:35+00:00

URL: https://externals.io/message/129271#129271

> Hi all,
>
> The Block Scoping RFC and the Context Manager RFC cover a lot of similar
> use cases, and a lot of the discussion on both threads has been
> explicitly comparing them.
>
> To try to picture better how they compare, I have put together a set of
> examples that implement the same code using both features, as well as
> some other variations, in this git repo:
>
> https://gitlab.com/imsop/raii-vs-cm
>
> A few notes:
>
> - The syntax for the two proposals is based on the current RFC text. If
> they are updated, e.g. to use different keywords, I will update the
> examples.
>
> - I have included examples with closures which automatically capture by
> value, since a lot of the same use cases come up when discussing those.
>
> - There are many scenarios which could be included, and many ways each
> example could be written. I have chosen scenarios to illustrate certain
> strengths and weaknesses, but tried to fairly represent a "good" use of
> each feature. However, I welcome feedback about unintentional bias in my
> choices.
>
> - Corrections and additional examples are welcome as Merge Requests to
> the repo, or replies here.
>
>
> With that out of the way, here are my own initial thoughts from working
> through the examples:
>
> - RAII + block scope is most convenient when protecting an existing
> object which can be edited or extended.
>
> - When protecting a final object, or a native resource, RAII is harder
> to implement. In these cases, the separation of Context Manager from
> managed value is powerful.
>
> - Context Managers are very concise for safely setting and resetting
> global state. RAII can achieve this, but feels less natural.
>
> - An "inversion of control" approach (passing in a callback with the
> body of the protected block) requires capturing all variables *not*
> scoped to the block. Even with automatic by-value capture, those needed
> *after* the block would need to be listed for capture by reference.
>
> - Building a Context Manager from a Generator can lead to very readable
> code in some cases, and closely mimics an "inversion of control"
> approach without the same variable capture problems.
>
>
> I would be interested in other people's thoughts.
>
> Regards,
>
> --
> Rowan Tommins
> [IMSoP]


Another suggestion would be to follow the Java try-with-resources 
syntax. It does not require a new keyword to be introduced, as with the 
Context Manager syntax. Moreover, it aligns with current 
try-catch-finally usage already implemented by PHP developers.

try ($transaction = $db->newTransaction()) {
     $db->execute('UPDATE tbl SET cell = :cell', ['cell'=>'value']);
}

Any object that implements TryWithContext can be used with such syntax. 
The function returns the exit context operation as callback.

interface TryWithContext {
    public function tryWith(): \Closure;
}

For a transaction it might look like this. Rather auto-capture I'd 
suggest explicit complete scope capture, by using the use keyword 
without parenthesis.

class Transaction implements TryWithContext {
     public function tryWith(): \Closure
     {
         $this->db->beginTransaction();
         return function (?\Throwable $e = null) use {
             if ($e) {
                 $this->db->rollbackTransaction();
                 return;
             }

             $this->db->commitTransaction();
         };
     }
}
