On Fri, Nov 6, 2026, at 3:40 AM, David Maye wrote:
> Hello,

Please remember to bottom post, not top post.

> I agree that `as` seems more coherent than `=>` in PHP. The only time I 
> saw `=>` in PHP was with key => value. And in JS it was with `() => {}` 
> functions.
>
> I have another question. This mechanism of Context Manager, Is it the 
> same as the Ruby `do` blocks? Example with Vagrant Ruby configuration 
> file:
>
> ```
> Vagrant.configure("2") do |config|
>   config.vm.box = "bento/ubuntu-24.04"
>   config.vm.box_version = "202510.26.0"
> end

It's not quite the same.  I don't have any Ruby experience, so going based on 
https://zetcode.com/ruby/do-keyword/, it can be used in a similar way but it's 
not the same mechanism.  Ruby (per that page) creates a closure for a do block, 
and thus variables go out of scope at the end and get closed implicitly.  A 
using block in this RFC creates no closure or scope.  The body of the using 
expression executes in the same function context as the code around it.  Also, 
the context manager generator itself allows more cleanup than just "unset()" on 
the context variable.  That happens automatically, which can trigger some 
cleanup, but the context manager is able to do a lot more if it wants to.

The model we are building from is Python, basically.

> When you set the example as:
>
> ```
> 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.
> ```
>
> It means that the block inside `using` is aware of variables outside of 
> it's own scope, right?

Correct.  There is no "own scope".  As implemented currently, it's just 
materializing some generator read logic around the body of the using block.  
There is no new function scope created, so the code inside is "in" the function 
it's already in, as it always has been.

> I like the idea. I have to admit that at first I was confused because I 
> thought that the first example in the RFC post was exactly the same as 
> the second example (Error catching included).

You mean in the introduction?  They do accomplish the same goal, just with less 
code in the context manager version.

> I have another question: according to PHP documentation ("Freeing 
> resources"
>  
> https://www.php.net/manual/en/language.types.resource.php#:~:text=makes%20no%20sense.-,Freeing%20resources,-%C2%B6):
>
> "Thanks to the reference-counting system being part of the Zend Engine, 
> a resource with no more references to it is detected automatically, and 
> it is freed by the garbage collector. For this reason, it is rarely 
> necessary to free the memory manually."
>
> From what I understand by this text, `fclose()` is optional (but 
> recommended according to some Stack Overflow posts). In both cases 
> (using or not the using `using`), this acts exactly the same. The only 
> difference is that you declare the variable inside the using instead of 
> the outside the try/catch block, right? Because even inside the `using` 
> function you would need to invoke the `fclose()` function, right?

PHP will automatically close() a resource that goes out of scope, just as it 
will garbage collect an object that goes out of scope.  However, that is only 
true if that is the last reference to that resource/object.  If the value had 
"escaped" (see the section in the RFC), then the file wouldn't be closed at 
that point.  Also, even if PHP will cleanup as it goes, it's still good 
practice to close a file when you're done with it to minimize race conditions.  
A using block takes care of both of those for you.  The context manager 
generator function is where the fclose() would live, so you don't have to 
remember to write it yourself every time.

> Apart from easing the expressiveness of the language, I'm curious of 
> what would be other benefits. In the post you express that it provides 
> "a way to abstract out common control-flow and 
> variable-lifetime-management pattern". What are the ways this function 
> may bring such improvements? Are those improvement observed by language 
> like Python not already available in PHP by default? I read somewhere 
> that PHP tends to be more memory efficient than Python due to the 
> processing of the many magic methods and other issues. If so, Is the 
> context manager in Python focused on improving the 
> variable-lifetime-management due to Python internal issues, and are 
> these issues present in PHP?

The examples section includes most of the example cases I could think of off 
hand, but I'm sure there are more.  Basically, any time you have the use case 
of "I want to stick some setup logic at the start of this code, and some 
cleanup and error handling logic at the end", a context manager can abstract 
that away for you, resulting in reusable logic and in your business logic not 
getting confused with the boilerplate error handling.

Think of opening a connection to some remote service and sending a message to 
it, but then there's like 10 error cases you need to handle.  That's a great 
example to factor out into a using block, so you don't need to do all that 
error handling each time.

For use in Python, I recommend this video, which lays out a "Pythonic" way of 
thinking, and in particular shows how context managers in Python can help 
vastly simplify code.

https://www.youtube.com/watch?v=wf-BqAjZb8M

(That's the video that really helped me wrap my head around context managers 
and made me want them in PHP.)

As far as performance, there's a huge number of differences between PHP and 
Python that impact performance.  The engine itself is less efficient, plus yes, 
Python relies a lot more heavily on magic callbacks that incur extra overhead 
(just as they do in PHP).  You can't really pin it down to any one thing.  
Context Managers in Python in particular are mainly about managing flow of 
control and error handling, not performance, which is the same for this RFC.

The way using is implemented here, that impact is minimal.  It adds a generator 
invocation and read, and that's about it.  So it's not 100% free, but the 
overhead is minimal, and comparable to if you were passing a closure to some 
ordinary function that did the same sort of wrapping.

--Larry Garfield

Reply via email to