> 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