Hi! It's been a few days since I wanted to send this email to internals, but real life has been a bit chaotic so I apologize if it comes off as if I didn't research the archives enough. I glossed over the Module conversation from 10 months ago and the one that recently surfaced and after deeply thinking about Rowan's and Larry's comments I wanted to throw this idea into the pit.
Lets preface the conversation with the fact that 1) a module system for PHP has been discussed for several years and 2) if there was an easy and perfect solution it would have been long implemented by now. With that in mind, I think there are mainly two major "camps": the ones that would support something new similar to Node ESM vs CommonJS and those who won't. Having dealt with this mess on the NodeJS side, I'm still on the side that would support it because even though it's been 10 years worth of "mess", it has greatly empowered progress. But I think PHP is too conservative to indulge this camp, so I'm going to focus on Rowan's and Larry's position of "we need something that builds on top of namespace, not replace it". If we consider how GitHub, Composer and Docker Hub works, we can pin a very important aspect of "namespaces": {entity}/{project}. Entity may either be an individual or an organization, but the concept is mostly the same. Although it can be argued that PHP has nothing to do with that, I think that could be a "good-enough" foundation considering the complexity of the subject. Here is what we could do: ```php <?php declare(strict_types=1); namespace Acme\ProjectOne { public class Foo {} // same as class Foo {} private class Bar {} // only visible inside Acme\ProjectOne protected class Baz {} // visible inside Acme } namespace Acme\ProjectTwo { new \Acme\ProjectOne\Foo; // Work as always new \Acme\ProjectOne\Bar; // Fatal error: Uncaught Error: Cannot instantiate private class \Acme\ProjectOne\Bar from \Acme\ProjectTwo new \Acme\ProjectOne\Baz; // Works } namespace Corp\Corp { new \Acme\ProjectOne\Foo; // Work as always new \Acme\ProjectOne\Bar; // Fatal error: Uncaught Error: Cannot instantiate private class \Acme\ProjectOne\Bar from \Corp\Corp new \Acme\ProjectOne\Baz; // Fatal error: Uncaught Error: Cannot instantiate protected class \Acme\ProjectOne\Baz from \Corp\Corp } function (\Acme\ProjectOne\Foo $foo) {} // Works as always function (\Acme\ProjectOne\Bar $bar) {} // Open question: allow or disallow it? function (\Acme\ProjectOne\Baz $baz) {} // Open question: allow or disallow it? ``` This would allow public, private and protected classes in a way that I believe to be useful for the large ecosystem that surrounds Composer. From my extremely limited understanding of the engine, I think the easy/natural step would be to allow private/protected classes to be *received* outside its namespace because a type declaration does not trigger autoload. However, an important question is whether this is enough groundwork that could lead to optimizations that have been discussed when the topic of module is brought up. For instance, if type-hint outside the module is disallowed, could that make it easier to pack and optimize an entire module if we could instruct PHP how to load all symbols of a namespace all at once? I don't know. ------------------------ As I'm writing this down I don't know if it could be related or if its something only making sense inside my head, but I see the above proposal paired with a potential amendment to PSR-4 (and Composer), to stimulate the community to pack small related symbols in a single file with an opt-in approach: composer.json: ``` // ... "autoload": { "psr-4-with-module": { "App\\": "app/", } }, // ... ``` ``` <?php declare(strict_types=1); // app/Foo/Bar.php namespace App\Foo; class Bar {} // app/Foo.module.php namespace App\Foo; enum Baz {} enum Qux {} new \App\Foo\Bar; // loads app/Foo/Bar.php \App\Foo\Baz::option; // file app/Foo/Baz.php does not exist, tries app/Foo.module.php before giving up \App\Foo\Qux::option; // app/Foo.module.php has been loaded and Qux has been registered already ``` Thoughts? -- Marco Deleu