First off, in 10 years of using gmail I've never had it lose an email. Well, it happened after I spent 4 hours on this. So, this is sorta iteration 4. I'll type this up in Visual Studio code and then paste to gmail.
The Wordpress discussion about composer and the decision not to use it keys in the features a package management system must meet. These are * Command Line should not be required * Plugins using version X of a package should not be affected by plugins using version Y * Install and maintenance of the site should remain possible from the browser alone. * Backwards compatibility must be maintained. A core PHP package management system should be a revision of what's come before that doesn't disturb what has come before. PHP packages are as follows: * Extensions, written in C++ * PECL Libraries, which I believe can be in PHP or C, but are server-wide * Phar archives * Composer libraries, which are always in PHP and leverage namespaces, PSR-4 convention and the autoload system. Some of my prior discussions have been about what I'd like to see in a new module system, but for scope, clarity, and sanity reasons I'm going to set that aside. (Not to mention some of the more controversial pieces have been there) Within the package management system there is a single new keyword - import. I'll go into details on it in a bit but suffice to say its behavior is different from include/require. In this schema a PHP application is a collection of packages. Existing PHP code that does not use the import statement or the special directories mentioned below will not invoke anything discussed on this page and will not need to change in any way. Applications The application is the root package. It is the package that imports to the root namespace. When PHP is asked to parse a file it will look for a `.php-packages` folder, first in the current working directory then in parent directories. If it doesn't find one, business as usual. If we do find one we follow its directives about setting up an application environment. The `.php-packages` folder is where PHP will put package related code for the application at hand. Code written explicitly for these changes will also put their package related files there - composer's vendor directory, composer.json, composer.lock, and so on - rather than putting those files in the site root. The folder is hidden to prevent web servers like nginx or apache from serving the files directly in any way. The .php-packages directory will have a configuration file called `php.mod`. This tells the parser: * How to initialize the application * What autoloaders are to be used * How to resolve import Let's look at what such a file might look like for Drupal. For the moment I'm going to use go.mod's syntax. The final syntax to be used, be it ini, yaml, toml, json, is a discussion for another time. The part to focus in on here is what type of information do we need. package Drupal php 10 registry //packagist.org/packages composer init ( composer install ) require ( ./vendor/autoload.php ) imports ( //getcomposer.org/composer.phar ) The directives do the following: * package sets the name of the package if it is imported. Sort of irrelevant here, but present for consistency * registry sets up the default registry for the import statement and the loader used to install packages * init is the command(s) to run before the application is started for the first time. * require is the file(s) to require before running any file in the application * imports are the imports the package needs, in this case the composer.phar to load composer in locally. Now, given the popularity of composer some of these directives likely could be put in as logical defines, particularly the init, require and imports directives just being put in place if composer is selected as a loader. I don't rule out the possibility of a competitor to composer showing up one day though, as yarn was introduced as an alternative to npm. If this theoretical version of Drupal moves its composer.json and composer.lock files into `.php-packages` then the autoloader doesn't have to be required in the index.php file. Also, the application can be started without running `composer install` Import statement Given the Drupal application package in the previous section, we can have an extension file call out its dependencies in code rather than in config. import "twig/twig" But granted, there's not much point to this since Drupal already uses Twig. But suppose for the sake of argument that Symfony releases a Twig 4 with some major BC breaks, and we're working on a Drupal extension that wants to use the new features of that Twig before Drupal itself upgrades Twig in core. Well, now we can do this import "twig/twig ^4.0" as NewTwig Note that we have to mount this package off the root using the alias syntax above. If the new package isn't written with this system in mind then we'll end up having NewTwig prefixed on the normal namespace path which would end up looking like this use NewTwig\Twig\Environment However, if this new twig has a `php-mod` file then the name of the top level namespace must be put there, and all the other files do not have to call out that namespace at their top. This allows the alias to plug in more seamlessly allowing for this use statement use NewTwig\Environment Again, running two versions of the same package is not ideal, but sometimes it's unavoidable. Especially in large ecosystems like WordPress. Imported packages run on their own request thread (I think that's the best way - I'm sure the guys working on the egine know best). They don't see or affect anything outside themselves. They don't see global variables or even the superglobals. Namespace resolution for them is - touchy. We could do it like this: A symbol starting without a \ resolves locally, then goes up the chain till it hits the application root. This is most similar to the current namespace system, but it allows for hidden dependencies and frankly, that worries me. I'm more inclined to isolate package so that if they want to use something they need to import it for themselves even if the hosting application already has the lib. This means namespace resolution in a package stops at the root of the package. We end up with something like this namespace MyExtension import "twig/twig ^3.0" use \Twig\Environment The package manager should be able to provide this without needing to download the package twice. Note also in this import that we specify we want version 3 which we've tested our Extension with. If that matches the App, great! Only one copy of the code needed. If it doesn't, it's suboptimal but it will run. As mentioned above, import also needs to be able to load extensions. Currently extensions are locked into PHP - they can't advance at different rates. This has led to several extension improvements getting abandoned over BC concerns. However, this would be nice import "ext://mysql ^2.0" Architecturally this would allow the PHP suite to move to a more mono-repo style with the various extensions having defaults for the current PHP distribution and newer versions available. It would also stop a repeat of having to have both mysql and mysqli functions loaded at the same time. This is enough to chew on for now. I'll take notes from the conversation that follows and iterate again.