> On Jul 8, 2024, at 5:41 AM, Rowan Tommins [IMSoP] <imsop....@rwec.co.uk> 
> wrote:
> I agree. I wrote most of the below a couple of days ago, but I don't think it 
> posted correctly, so apologies if some people see it twice: 
> 
> Autoloading is just a way to load files later, by the engine telling you when 
> a class is first needed. PHP does not, and should not, make any assumptions 
> about how files are laid out on disk; an autoloader doesn't actually need to 
> load any files at all, and if it does, it uses the same include or require 
> statements which have been in PHP for decades.

I think maybe you are replying to an earlier iteration by Michael Morris and 
have not seen the more recent iteration?  

There he explored adding an additional function to named `spl_autoload_map()` 
where the difference from `spl_autoload_register()` is that while the latter 
uses procedural code to determine what should be loaded the former would use a 
declarative map to determine what should be loaded. Then Composer and/or other 
tools could/would generate that map for PHP.

With an `spl_autoload_map()` PHP would not need to make any assumptions about 
how files are laid out on disk. Instead, PHP would use a schema of a 
yet-to-be-determined data representation format to discover  declaratively 
where files needed to be laid out on disk.

> Likewise, installing packages and defining version schemes is a completely 
> separate problem space that can probably be served by a few small tweaks to 
> Composer once the language provides the underlying functionality.
> 
> The core of the problem you seem to want to solve is this: if you have two 
> files foo_1.php and foo_2.php, which both define a class \Acme\Foo, how do 
> you load both of them, so that you end up with two differently named classes? 

That is one (1) of the core problems, yes.

> In JS, that's easy, because functions and object constructors (and "classes") 
> exist as objects you can pass around as variables, they don't need to know 
> their own name. In PHP, everything is based on the idea that functions and 
> classes are identified by name. You can rewrite the name in the class 
> declaration, and in direct references to it, but what about code using 
> ::class, or constructing a name and using "new $name", and so on? How will 
> tools using static analysis or reflection handle the renaming - e.g. how does 
> DI autowiring work if names are in some sense dynamic?

This is one of the unfortunate  aspects of PHP never makes types a first-class 
data type. But I digress.

> You've also got to work out what to do with transitive dependencies - if I 
> "import 'foo_1.php' as MyFoo", but Foo in turn has "import 'guzzle_2.php' as 
> MyGuzzle", what namespace do all Guzzle's classes get rewritten into? What 
> about dependencies that are specifically intended to bridge between packages, 
> like PSR-7 RequestInterface?

Which is a direct result of the other problem you mentioned, i.e. IOW without 
attempting to address the prior problem this would not be a problem. #fwiw

> My advice: start with the assumption that something has already installed all 
> the files you need into an arbitrary directory structure, and something is 
> going to generate a bunch of statements to load them.

And this sentence is why I chose to reply to your message.  That assumption 
itself blocks the needs of user-managed apps.

(Did you happen to read my compare-and-contrast of user-managed vs. 
developer-managed apps from a few days ago?)

I feel it is likely those who have never worked professionally in PHP on 
user-managed apps like WordPress  — which I assume describes you accurately? — 
are probably just simply unaware of the problems that your assumptions cause 
for user-managed apps. And yes, some developers have no empathy for others who 
have different circumstances, but I honestly don't think you (Rowan) are in the 
category. 

Developer-managed apps use a build tool to put all vendor code in a single 
hierarchical set of namespaces and then load needed code from there. But that 
really does not work for user-managed apps like WordPress or Drupal.  Or at 
least not as they exist today, and probably not even if they were rearchitected 
for the start.

What works for user-managed apps is that each `add-on` (`plugin` in WordPress, 
`module` in Drupal) is stored in its own self-contained directory containing 
its own vendor code — where some of the vendor code could easily be duplicated 
in another add-on — and then the user-managed apps itself manages loading of 
all add-ons itself without a PSR-4 autoloader. As it exists, there are no 
standard for how add-on filenames and directory structures much be named nor 
how they are to load their dependencies so it is impossible for WordPress or 
Drupal to take on that role using PSR-4 for them. 

Michael Morris' idea to add an `spl_autoload_map()` function would allow 
addressing the needs of user-managed apps that treat each add-on as a 
self-contained entity. But making the assumption that "something has already 
installed all the files you need into an arbitrary directory structure" is not 
sufficient for the problems Michael Morris and I have been trying to address.

An autoloader map schema that has enough information for PHP to understand how 
to manage the conflicting names, and for the user-managed apps and Composer to 
be able to tell PHP what names are conflicting is in fact a solid way forward.

-Mike

Reply via email to