Sorry for the late feedback, it's hard juggling all the different RFCs that are in progress to provide meaningful feedback.
Am 2026-03-11 22:07, schrieb Jakub Zelenka:
> I also think that there is not really much use case for user space to
> implement their own handles so such interface would be used only
> internally
> anyway.
This applies equally to interfaces and abstract methods. The abstract
base class however will make it much weirder when a specific (future)
handle might need to implement additional interfaces or abstract
classes.
> In addition interface would effectively expose the internal stream fd
> which
> is currently hidden and makes harder messing up with stream fd which
> might
> cause various issues.
I don't understand that point. For both an interface and an abstract
method, the method would exist on the child class and thus can be called
by a developer.
Well if it is abstract, then the method can be protected and because the
classes are final, user spaces cannot call it. But for interface I would
Protected methods of internal classes should still be accessible to Reflection.
need to make it public which means that StreamHandle would need to expose
callabable (public) method. I know that I could just return 0 and use
different handling internally but I think this would be surprising and
created obvious inconsistency. I mean it's fine if the calls happen
internally but if the exposed methods are just dummy and return nonsense
for user space, then I don't think it would be a good design.
It's equally weird that there is a protected method that is effectively internally called by an unrelated class (Context) that is not supposed to know about it. Perhaps the correct solution would then be removing the `getFileDescriptor()` method from the public API entirely and change `Handle` to be an empty “marker interface” that cannot be implemented in userland (similarly to Throwable) to leave all options open for the future?
Just a heads up that I plan to open voting on Tuesday 31st March around the same time like now.
Kind regards,
Jakub
Hi, Jakub!
Why do you use get and is methods if we have powerful prioritize with get hooks nowadays? I think that PHP should promote its modern features in its own API.
Just a heads up that I plan to open voting on Tuesday 31st March around the same time like now.
Kind regards,
Jakub
Hi, Jakub!
Why do you use get and is methods if we have powerful prioritize with get hooks nowadays? I think that PHP should promote its modern features in its own API.
There is actually no internal API for hooks so it would require using object handlers (which is from the user space point of view just __get). It means no stubs declaration either. We also don’t have an internal policy where to use hooks and where methods. So there are still lots of blockers to start using it in core.
On Tue, Mar 31, 2026 at 11:23 AM Tim Düsterhus <tim@bastelstu.be> wrote:
Hi
Sorry for the late feedback, it’s hard juggling all the different RFCs
that are in progress to provide meaningful feedback.
Am 2026-03-11 22:07, schrieb Jakub Zelenka:
I also think that there is not really much use case for user space to
implement their own handles so such interface would be used only
internally
anyway.
This applies equally to interfaces and abstract methods. The abstract
base class however will make it much weirder when a specific (future)
handle might need to implement additional interfaces or abstract
classes.
In addition interface would effectively expose the internal stream fd
which
is currently hidden and makes harder messing up with stream fd which
might
cause various issues.
I don’t understand that point. For both an interface and an abstract
method, the method would exist on the child class and thus can be
called
by a developer.
Well if it is abstract, then the method can be protected and because
the
classes are final, user spaces cannot call it. But for interface I
would
Protected methods of internal classes should still be accessible to
Reflection.
Good point.
need to make it public which means that StreamHandle would need to
expose
callabable (public) method. I know that I could just return 0 and use
different handling internally but I think this would be surprising and
created obvious inconsistency. I mean it’s fine if the calls happen
internally but if the exposed methods are just dummy and return
nonsense
for user space, then I don’t think it would be a good design.
It’s equally weird that there is a protected method that is effectively
internally called by an unrelated class (Context) that is not supposed
to know about it. Perhaps the correct solution would then be removing
the getFileDescriptor() method from the public API entirely and change Handle to be an empty “marker interface” that cannot be implemented in
userland (similarly to Throwable) to leave all options open for the
future?
This (marker interface just for internal classes) is actually a really good idea. Will change it.
There is actually no internal API for hooks so it would require using
object handlers (which is from the user space point of view just __get). It
means no stubs declaration either. We also don't have an internal policy
where to use hooks and where methods. So there are still lots of blockers
to start using it in core.
While I agree with the conclusion that using hooks internally is complicated and there is no real policy there, Valentin was actually making a good point: We could use regular `readonly` properties for those cases where we're just exposing a “constructor parameter”. Specifically:
- Context::getBackend() -> public readonly Backend $backend;
- Watcher::getHandle() -> public readonly Handle $handle;
Potentially Watcher::$data could also be a regular (non-readonly) property, or does `modifyData()` contain additional logic that is not just “store the value somewhere”?