RFC Draft - Improved Autoloading

From: Date: Tue, 07 Jul 2026 03:06:20 +0000
Subject: RFC Draft - Improved Autoloading
References: 1 2 3  Groups: php.internals 
Request: Send a blank email to internals+get-131784@lists.php.net to get a copy of this message
After feedback from Rowan Tommins, Larry Garfield, pmjones and Alex Rock I'm going to move to a first draft of a spec for this idea. INTRODUCTION Numerous attempts have been made to create function and constant autoloaders within namespaces, and they've ran into problems concerning symbol lookup. This RFC proposes to sidestep this issue by allowing userland to register an improved autoloader able to not only handle the first time classes are sought out by the engine, but also the first time the engine sees a namespace. This allows userland code to set up a namespace - load its functions, constants and/or perform other initialization work deemed necessary by the user. PROPOSAL Users will be able to provide a callback to spl_autoload_register() that has two string arguments instead of one. If they do those arguments are as follows. ``` function (string $class, string $namespace) {} ``` When the engine encounters a class that it does not have on the symbol table it will invoke the callback for the class as it presently does. The namespace argument will only be populated if the engine has not seen this namespace. For example ``` $a = new A\AClass(); $b = new A\BClass(); ``` Line 1: Autoloader will be called with arguments ("A\AClass", "A") Line 2: Autoloader will be called with arguments ("A\BClass", null) PHP will also call the autoloader when it encounters the namespace keyword referencing a namespace it hasn't seen before. Hence ``` namespace B; ``` This will result in a call to the autoloader with arguments (null, "B") If a namespace chain is encountered only one call is made. Hence ``` namespace A\B\C; ``` Will result in a call to the autoloader of (null, "A\B\C"). NOTE. The engine will mark namespaces "A" and "A\B" as seen in addition to the specified namespace "A\B\C", so the autoloader needs to work out if it should do anything for those namespaces as well. BACKWARDS INCOMPATIBLE CHANGES None foreseen. I guess technically if someone has already written an autoloader that takes 2 or more arguments the code would break because the engine previously was not sending 2 arguments. However, is this a realistic thing to worry about? I can't think of a rational reason to write such an autoloader. Note that autoloaders written to this spec should happily run on older PHP versions because those versions will always give null to the 2nd argument causing the autoloader to only act on its class code. An autoloader that prepares namespaces based on classes is still possible, but unsafe since a function from the namespace could get called. PROPOSED PHP VERSIONS This should be safe on any minor release. Realistically this won't be available until 8.7 I would guess as we're already in 8.6 alpha. I don't think this could be coded before feature freeze, but I don't know the engine well. I think I can do this myself though if needed, especially if someone volunteers to coach me. RFC IMPACT This RFC allows a route to function autoloading by sidestepping issues it has had. Quoting Rowan Tommins (with example updated to reflect this proposal): > This really nicely side-steps the global-vs-namespace sequence problem > that function autoloading always runs into: by the time the engine > reaches an unqualified name, the namespace loader has already run for > the current namespace, and defined any functions it wants. The engine > can fall back to the global namespace, and error immediately if that > fails, without an extra autoload call. > > To illustrate: > > namespace Acme\Foo\Widgets; > use Omnicorp\Bar\Helpers; > $name = make_widget_name(); > echo strlen($name); > Helpers\spin_wheels(); > > Line 1: All autoloaders that accept 2 arguments are called with arguments > (null, 'Acme\Foo\Widgets') > >Line 2: Use statement, has no run-time effect > > Line 3: Attempt to call Acme\Foo\Widgets\make_widget_name(); this might > have been defined by the loader at line 1. If it doesn't exist, attempt > to call \make_widget_name(); if that doesn't exist, throw an Error. > > Line 4: Attempt to call Acme\Foo\Widgets\strlen(); if that doesn't > exist, call \strlen() which is built-in, so never fails. > > Line 5: Attempt to call Omnicorp\Bar\Helpers\spin_wheels(); if it > doesn't exist, call all autoloaders that accept two arguments with arguments > (null, 'Omnicorp\Bar\Helpers') and try again. If it still doesn't exist, throw > an Error. And to extend on his example, when a class is referenced from a previously unknown namespace the autoloader will receive both arguments as outlined above and be responsible for executing both setup processes. This RFC will almost certainly trigger a related PSR standard that takes namespace setup into account. Once that is settled the maintainers of composer will likely implement such a standard. One possible route is to follow Python's lead of having a __setup__.php file in the namespace's directory if the namespaces are set up in mirror to the file system setup, but nothing in this RFC mandates that approach. >

« previous php.internals (#131784) next »