On Mon, Jul 6, 2026, at 10:06 PM, Michael Morris wrote:
> 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.
"So many problems in programming come from making one thing try to do two
things." --I forget who
I quite like the idea of having a "namespace autoload file" (or files). It
seems like it would neatly side step most issues with function autoloading, and
offer a place for "small stuff" that arguably doesn't need its own file: A 2
element enum, typedefs if we ever get them, empty exception classes, etc. I'd
support going this route.
However, like others, I dislike shoving both autoload paths into a single
callback function. Just let it be its own utility, independent of class
autoloading. Having to think about many different code paths in a single
function (how do I behave on string, null; null, string; and string, string;
and wait, what about null,null?) is bugs waiting to happen and needlessly
confusing.
Let's also remember that there's really only one autoloader that matters for
most projects: Composer. And that autoloader is called hundreds or thousands
of times on every request, in an FPM type setup. Adding even a single
if-statement to that function would have a performance impact on nearly every
PHP project in the world, and in practice this approach would require adding
several, I'm sure.
Just make it its own autoload registration system and be done with it.
Otherwise, I like this approach better than most function autoloading proposals
that have come up, because it doesn't push toward function-per-file, which I
don't think anyone wants.
As far as FIG and Composer, I'm not sure we'd even need a PSR. Composer would
likely just add an "autoload_namespaces" key, which maps namespaces to a file
or files, and do it itself. The only use for a PSR would be to have some
standard name that Composer would automatically register; it's up to the
Composer team if they would benefit from that. I'm happy to help on the FIG
side if so, but that's really their call.
--Larry Garfield