On Mon, Jul 1, 2024 at 9:02 AM Larry Garfield <la...@garfieldtech.com> wrote:
> 2. Supporting multiple versions of the same class is *waaaay* out of > scope. No, it's actually the heart of the problem now that I've had a few days to think on this, and it's something an autoloader can NOT resolve. > You seem to imply Composer is the reason we cannot do that. That's > incorrect. PHP has a single global symbol table for classes. (And a > separate one for functions for not-great historical reasons.) Trying to > define the same class twice will fatal the engine. While there are some > screwy conditional-include games you can play, they're fragile and still > would not allow WP Plugin A to use v1 of a library and WP Plugin B to use > v2 of a library. I am not versed in that part of the engine, but I would > be shocked if splitting up the global symbol table was possible, let alone > feasible. > > Let's assume all that's true. Nothing you said stops this import 'package v1' as \Package import 'package v2' as \NewPackage The problem with the current situation is the top level namespace of packages are baked into the files. The import statement can alias the top level namespace. Even if the engine cannot maintain multiple symbol tables, what it can do is apply this aliasing on the fly as the same sort of hack to the language that the current namespace implementation is (it's a blind string replace, which is why they switched the namespace operator from :: to the bloody escape character). But for the alias to work the package has to tell import what its top level namespace name is, especially for when the file is imported without an alias, so that name will be used to graft the code in the package onto the symbol table. To illustrate, a package with a single file, its contents are class TestClass {} Note, no namespace declared in the file itself. The minimum contents of the package declaration file, whatever form it takes, is: namespace TestPackage; With just that in place there's no reason I can see for the engine to be unable to do this. import 'testpackage'; \TestPackage\TestClass // This is actually created symbol import 'testpackage' as NewPackage \NewPackage\TestClass // This is the actually created symbol. Set aside for a moment how the import statement resolves 'testpackage' - the rules for resolving paths, urls, and version numbers are a different topic. But to say there is no way this can be done - bah. What this does cut off at the knees though is allowing users who want this flexibility to divest their control over what gets loaded for their code to the discretion of an autoloader. Much of the time, that's ok, but in more complex applications it backfires. Sorta like typeless variables themselves. For beginning programmers writing simple code they're fine. I know - I was one - and this simplicity hooked me in where I initially couldn't get my head around datatyping with C# when I was young. But at the opposite end of the spectrum it backfires as having little to no control over data types creates at least as many problems as it solves, especially for automated testing. We can have it both ways though. Let the infrastructure in place for autoloading to stay in place, which will include the version of the code called out in composer.json (assuming composer handles autoloading). But if I want to use a specific version of a package, even one that is in the overall application I'm writing for such as WordPress or Drupal, I should be able to do that. But that's going to require aliasing the package's name as outlined above.