Hi

On 2026-09-09 10:48, Casper Langemeijer wrote:
It also violates the exception policy in
https://github.com/php/policies/blob/main/coding-standards-and-naming.rst#throwables,
which states:

> If an extension uses external functionality that may throw an exception it 
MUST wrap any exception thrown by that functionality into an appropriate exception 
of its own. It MUST set the $previous property to the original exception when 
doing so.

I've read this last week and this interpretation of the exception policy has taunted me since then. Tim, I think you are mistaken in your point of view on this. I'm not aware of any point where exceptions thrown in user callback methods are wrapped, but at least autoloading, a very prominent one, does not. https://3v4l.org/vYmts Changing this (in general for all user callbacks) would be a very inconvenient BC break for many projects.

Yes, much of the existing standard library predates the policy and more generally also predates any kind of API *design* regarding exceptions. The first part of the standard library where the Exception hierarchy got any real design is the new random API in PHP 8.2 - and that served as the blueprint for the new URI extension and the exception policy.

Regarding your specific example of autoloading, I'd argue that the correct behavior for autoloading is to wrap all exceptions. From a user perspective, autoloading is a blackbox service and it thus should behave like any other service (e.g. like the session example I have given in a previous email in this thread). In particular autoloading shows up “implicitly” in many cases and having a clear indicator that autoloading is what failed is useful. As an example, when using `class_exists()`, I don't want arbitrary exceptions to show up: https://3v4l.org/m0DIP#veol

I think this policy should be read differently. I think as a language user you should not have to be aware of the implementation of a functions internals. if some function is using something that could throw an exception this implementation detail should be hidden from the user. Also because if the function is re-implemented another way this exception could change. From the perspective of the language user, a callable provided to a function is not part of the functions internals.

I would agree for functions like `array_map()` or `array_filter()` where the sole purpose is executing the user callback and which cannot fail for other reasons. But for `preg_replace_callback()` and similar, the high level operation is “perform a replacement” and the provided callback is just an implementation detail. I would find it unexpected that `preg_replace()` with a broken replacement string (e.g. hypothetically referencing a group that doesn't exist, this case currently doesn't seem to emit an error) would throw `PregException`, but `preg_replace_callback()` with a broken replacement callback would throw arbitrary errors.

Best regards
Tim Düsterhusp

Reply via email to