[PHP-DEV] [Initial Feedback] PHP User Modules - An Adaptation of ES6 from JavaScript

Hello all. This is a ramble of an idea that’s managed to run around my head for a few days now. It isn’t fully formed, but I’ve ran the thought experiment as far as I can on my own and want to share it with all of you.

I’ve mostly been a lurker and I’ve seen a lot of RFC’s come and go. Of those not accepted many have been passed over because of background compatibility. And then there is the issue that PHP has multiple design flaws that seem impossible to get rid of. Finally, I sense from conversations I’ve read that there are a lot of engine parser optimizations that haven’t been tried because of the background compatibility problems present.

JavaScript was in this position as well 10 years ago when JavaScript modules were introduced with the ES6 syntax. Only recently have these modules finally begun to become first class members of node.js. The existing CommonJS require mechanism remains and will remain in Node for the foreseeable future, but the ES6 syntax allows an opportunity to sidestep the issue. The most significant of these is JavaScript modules run in strict mode, which actually removes features that are problematic for the engine or make it difficult to create optimized code.

Something similar could be done in PHP, and that’s what the remainder of this letter is about, but before I continue I want to make clear my vantage point: I am but a humble user of the code, I’m no expert on the underpinnings of the Zend engine. In the text to follow I’m going to make wrong calls on some things - maybe multiple things. I’m not married to anything here. Further, even if I were a master of the engine and knew where to start, the scope of this is too large for any one person to undertake.

So all that said, I’ll begin.

PHP User Modules are php files that are brought into the runtime through a new parser that is able to generate faster and more concise runtime code by removing support for problematic features and imposing a strict mode by default. They focus on PHP as a language and not as a template engine.

The only background compatibility break is the introduction of three keywords: “import”, “export” and “from”

The PHP interpreter does not load PHP files as modules unless it is directed to do so in an ini file or an .htaccess file using the default_filetype directive. If this directive is missing its value will be “default” - the value “module” will be used to trigger loading the initial PHP file as a module, and further types could in theory be introduced at a far later date.

Again, this setting only affects the INITIAL PHP script file loaded by the interpreter, such as the index.php of Drupal. Files that are included with include, include_once, require, or require_once will be imported as they always have. Files that are included with import are PHP User Modules.

User Module Files
PHP User Modules have the following properties (Proposed, and very much subject to change):

  • They are code files. They have no <?php or ?> tags, and the inclusion of those tags is a parse exception. I know this will be problematic for PHP storm and other IDE’s, but it’s not an insurmountable problem.
  • If the removal of HEREDOC and NOWDOC syntax would simplify the parser, then these too would be removed from User Modules.
  • They have no starting symbol table. Each class, function or constant to be used must be imported with the import statement. Symbols declared in a user module do not affect the symbol tables of the rest of the runtime.
  • They have their own variable scope. They do not by default see globals or superglobals. Variables declared in a module remain in that module. Superglobals can be imported (Ideally this is an opportunity to provide new more secure ways of accessing this data as several userland libraries have done).
  • They have no support for braceless syntax (which is only really useful when PHP is used as a template engine).
  • User Modules run in strict mode.
  • Exceptions only. trigger_error will cause a parse exception.
  • The @ error suppression operator is not supported.
  • Top level return to stop parsing of the file early (as in include and require) is not supported.
  • If at all possible, . as a connotation operator will not be supported and instead that operator will be used for scope resolution instead of the three scope resolution operators currently in use for legacy reasons (::, → and \ )
  • Other language features whose use is considered bad practice are also up for chopping.

Import Statement
PHP User modules are loaded by importing them, not by using include or require. It’s syntax is similar to JavaScript’s, but not exact - for one unlike JavaScript there need not be a from clause.

User Modules can’t use code that hasn’t been imported to their symbol table. So if you want to use str_pos you need to import it

import str_pos

An import of a symbol will search for that symbol using the existing resolution rules, and if the symbol is not found the autoloaders are invoked. Once all have ran the import is retried and if the symbol now exists globally it can be imported. This somewhat weird approach ensures that user modules aren’t cut off from the existing ecosystem.

Why not just require, or bother with importing existing symbols? My idea here is clarity. It should be easier on the IDE’s and probably on the parser if these are called out. Also, explicitly importing functions makes it easier to get to fixed versions, which is a repeated stumbling block of many an RFC. I hereby invoke the ghost of PHP 6 and unicode. That failed because it was too much to do in one pass. Import allows language improvements to arrive piecemeal, and allows some of them to be userland. More on that in a bit.

As with Javascript, aliasing is allowed.

import str_pos as strPos

The fun really starts when the from clause shows up.

import foo from "foo.php"

The search order of import is as follows:

  1. Is the file in the same directory as the importing file? Yes, load.
  2. Is there a php_modules directory? If so, is the file in there?
  3. If the importing file is within the tree of the cwd (established by the first file loaded), then recursively look for a php_modules directory until at the cwd until the file is found (this is identical to the seek process of node with it’s analogous node_modules directory
  4. As a final try, consider the PHP include_paths.

This will of course require a package manager similar to composer to become part of core. However, composer will not be eclipsed as the import package manager (phppm?) is only concerned with user modules. These modules must explicitly export any symbols being fetched from them, whereas composer will continue to load files using require.

Imports can also be done against directories

import foo from "mypackage"

In this case the parser will look for “mypackage/index.php”

All exports of a file can be brought in with a wildcard

import * from "file.php"

Should a wildcard be allowed without the from clause? That is import *. To me this would mean “bring in the master symbol table” I’m not sure if that’s a good idea as it feels like a bad practice.

Also note, if foo.php doesn’t export foo, the import will fail with an exception. Which brings us to…

Export statement

PHP User Modules export code out using an export statement. If this didn’t happen there wouldn’t be much point to them. Constants, classes and functions can be exported. Unlike JavaScript, there is no default export as there isn’t an export object in the same sense as JavaScript.

export class Animal {}
export const pi = 3.141527
export function foo {}

As in Javascript exports can be sourced with a from clause. This is most frequently seen in packages.

export MyClass from "./MyClass.php"
export * from "./methods.php"

The wildcard allowing for all exports of another file to be exported at a common point, simplifying package interfaces.

Aliases are also possible. For example, say you want to use multibyte string functions by default. You can do this in one file now

export mb_str_pad as strPad;
export mb_str_split as strSplit;

And so on, then import

import * from "myMbAliases.php"

If you got this far, thank you. This overall idea to take one of the better things to happen to JavaScript in the last decade and incorporate it into PHP has been bothering me for awhile so I figured I’d share. I don’t know how much merit there is to this though.

Note there’s a lot more to JavaScript’s implementation of import and export that I only touched on here, but this letter has gone on long enough for a surface level idea pitch.

Mod Note: It’s been so long since I’ve sent any mail to the list that I’m getting mail from an address I no longer have access to - dmgx.michael@gmail.com. Is it possible to unsubscribe that email?

On Thu, Jun 27, 2024, at 04:15, Michael Morris wrote:

Hello all. This is a ramble of an idea that’s managed to run around my head for a few days now. It isn’t fully formed, but I’ve ran the thought experiment as far as I can on my own and want to share it with all of you.

I’ve mostly been a lurker and I’ve seen a lot of RFC’s come and go. Of those not accepted many have been passed over because of background compatibility. And then there is the issue that PHP has multiple design flaws that seem impossible to get rid of. Finally, I sense from conversations I’ve read that there are a lot of engine parser optimizations that haven’t been tried because of the background compatibility problems present.

JavaScript was in this position as well 10 years ago when JavaScript modules were introduced with the ES6 syntax. Only recently have these modules finally begun to become first class members of node.js. The existing CommonJS require mechanism remains and will remain in Node for the foreseeable future, but the ES6 syntax allows an opportunity to sidestep the issue. The most significant of these is JavaScript modules run in strict mode, which actually removes features that are problematic for the engine or make it difficult to create optimized code.

Something similar could be done in PHP, and that’s what the remainder of this letter is about, but before I continue I want to make clear my vantage point: I am but a humble user of the code, I’m no expert on the underpinnings of the Zend engine. In the text to follow I’m going to make wrong calls on some things - maybe multiple things. I’m not married to anything here. Further, even if I were a master of the engine and knew where to start, the scope of this is too large for any one person to undertake.

So all that said, I’ll begin.

PHP User Modules are php files that are brought into the runtime through a new parser that is able to generate faster and more concise runtime code by removing support for problematic features and imposing a strict mode by default. They focus on PHP as a language and not as a template engine.

FYI, in non-strict mode, this produces a deprecation warning that can be caught and thrown from:

(fn(int $x) => print($x))(123.456); // deprecation warning

but this will work

(fn(int $x) => print($x))(123.000); // this is fine

Both of those are errors in strict types, so you might be tempted to do

fn(int $x) => print($x))((int)$some_var);

but $some_var might not actually be an integer-like (such as null or a string that becomes zero).

Some of us prefer the more strict, non-strict mode as the built-in strict mode is actually … uhh, problematic, to say the least, in some business cases. So forcing strict mode is probably a non-starter.

The only background compatibility break is the introduction of three keywords: “import”, “export” and “from”

The PHP interpreter does not load PHP files as modules unless it is directed to do so in an ini file or an .htaccess file using the default_filetype directive. If this directive is missing its value will be “default” - the value “module” will be used to trigger loading the initial PHP file as a module, and further types could in theory be introduced at a far later date.

Again, this setting only affects the INITIAL PHP script file loaded by the interpreter, such as the index.php of Drupal. Files that are included with include, include_once, require, or require_once will be imported as they always have. Files that are included with import are PHP User Modules.

One of the advantages of the current autoloading file-loading system is that files are not included until the are used. This allows you to run MASSIVE projects that realistically only need to load dozens of files. For example, I know of some code-bases that have literally millions of PHP files collected over the last 15 years and hundreds of developers working on them every day.

User Module Files

PHP User Modules have the following properties (Proposed, and very much subject to change):

  • They are code files. They have no <?php or ?> tags, and the inclusion of those tags is a parse exception. I know this will be problematic for PHP storm and other IDE’s, but it’s not an insurmountable problem.

So, will ?> work? I have turned on output buffering and then just wrote out what I needed — ie, a template, then get the output.

  • If the removal of HEREDOC and NOWDOC syntax would simplify the parser, then these too would be removed from User Modules.

Are we sure we want multiple PHP parsers to maintain?

— Rob

On Thu, Jun 27, 2024, at 09:41, Rob Landers wrote:

On Thu, Jun 27, 2024, at 04:15, Michael Morris wrote:

Hello all. This is a ramble of an idea that’s managed to run around my head for a few days now. It isn’t fully formed, but I’ve ran the thought experiment as far as I can on my own and want to share it with all of you.

I’ve mostly been a lurker and I’ve seen a lot of RFC’s come and go. Of those not accepted many have been passed over because of background compatibility. And then there is the issue that PHP has multiple design flaws that seem impossible to get rid of. Finally, I sense from conversations I’ve read that there are a lot of engine parser optimizations that haven’t been tried because of the background compatibility problems present.

JavaScript was in this position as well 10 years ago when JavaScript modules were introduced with the ES6 syntax. Only recently have these modules finally begun to become first class members of node.js. The existing CommonJS require mechanism remains and will remain in Node for the foreseeable future, but the ES6 syntax allows an opportunity to sidestep the issue. The most significant of these is JavaScript modules run in strict mode, which actually removes features that are problematic for the engine or make it difficult to create optimized code.

Something similar could be done in PHP, and that’s what the remainder of this letter is about, but before I continue I want to make clear my vantage point: I am but a humble user of the code, I’m no expert on the underpinnings of the Zend engine. In the text to follow I’m going to make wrong calls on some things - maybe multiple things. I’m not married to anything here. Further, even if I were a master of the engine and knew where to start, the scope of this is too large for any one person to undertake.

So all that said, I’ll begin.

PHP User Modules are php files that are brought into the runtime through a new parser that is able to generate faster and more concise runtime code by removing support for problematic features and imposing a strict mode by default. They focus on PHP as a language and not as a template engine.

FYI, in non-strict mode, this produces a deprecation warning that can be caught and thrown from:

(fn(int $x) => print($x))(123.456); // deprecation warning

but this will work

(fn(int $x) => print($x))(123.000); // this is fine

Both of those are errors in strict types, so you might be tempted to do

fn(int $x) => print($x))((int)$some_var);

but $some_var might not actually be an integer-like (such as null or a string that becomes zero).

Some of us prefer the more strict, non-strict mode as the built-in strict mode is actually … uhh, problematic, to say the least, in some business cases. So forcing strict mode is probably a non-starter.

If you want to see what I mean:

non-strict: https://3v4l.org/kZ09l

strict: https://3v4l.org/5kVSG

— Rob

Le 27 juin 2024 à 09:41, Rob Landers rob@bottled.codes a écrit :

PHP User Modules are php files that are brought into the runtime through a new parser that is able to generate faster and more concise runtime code by removing support for problematic features and imposing a strict mode by default. They focus on PHP as a language and not as a template engine.

FYI, in non-strict mode, this produces a deprecation warning that can be caught and thrown from:

(fn(int $x) => print($x))(123.456); // deprecation warning

but this will work

(fn(int $x) => print($x))(123.000); // this is fine

Both of those are errors in strict types, so you might be tempted to do

fn(int $x) => print($x))((int)$some_var);

but $some_var might not actually be an integer-like (such as null or a string that becomes zero).

Some of us prefer the more strict, non-strict mode as the built-in strict mode is actually … uhh, problematic, to say the least, in some business cases. So forcing strict mode is probably a non-starter.

Hi,

There is no equivalent of “strict mode” in PHP. Do not confuse it with “strict_types”, which has nothing in common except the word “strict” in its name…

Strict mode in JS was introduced to disable design mistakes that couldn’t be removed due to very strong (almost inflexible) BC contraints. In PHP, we have deprecations followed by removals in next major version.

(And some people, including me, will argue: while JS strict mode disables design mistakes, PHP strict_types mode is a design mistake.)

—Claude

Hi Michael,

Hello all. This is a ramble of an idea that’s managed to run around my head for a few days now. It isn’t fully formed, but I’ve ran the thought experiment as far as I can on my own and want to share it with all of you.

I’ve mostly been a lurker and I’ve seen a lot of RFC’s come and go. Of those not accepted many have been passed over because of background compatibility. And then there is the issue that PHP has multiple design flaws that seem impossible to get rid of. Finally, I sense from conversations I’ve read that there are a lot of engine parser optimizations that haven’t been tried because of the background compatibility problems present.

JavaScript was in this position as well 10 years ago when JavaScript modules were introduced with the ES6 syntax. Only recently have these modules finally begun to become first class members of node.js. The existing CommonJS require mechanism remains and will remain in Node for the foreseeable future, but the ES6 syntax allows an opportunity to sidestep the issue. The most significant of these is JavaScript modules run in strict mode, which actually removes features that are problematic for the engine or make it difficult to create optimized code.

Working with Typescript a little bit does give a vibe that PHP could borrow some of the concepts there and be improved greatly and I share this sentiment.

Something similar could be done in PHP, and that’s what the remainder of this letter is about, but before I continue I want to make clear my vantage point: I am but a humble user of the code, I’m no expert on the underpinnings of the Zend engine. In the text to follow I’m going to make wrong calls on some things - maybe multiple things. I’m not married to anything here. Further, even if I were a master of the engine and knew where to start, the scope of this is too large for any one person to undertake.

Who would build it is an extremely key aspect of making changes to PHP. Ideas are hard enough to survive the RFC process when there’s already an implementation. Finding a sponsor to work on this would be the first step.

So all that said, I’ll begin.

PHP User Modules are php files that are brought into the runtime through a new parser that is able to generate faster and more concise runtime code by removing support for problematic features and imposing a strict mode by default. They focus on PHP as a language and not as a template engine.

The only background compatibility break is the introduction of three keywords: “import”, “export” and “from”

The PHP interpreter does not load PHP files as modules unless it is directed to do so in an ini file or an .htaccess file using the default_filetype directive. If this directive is missing its value will be “default” - the value “module” will be used to trigger loading the initial PHP file as a module, and further types could in theory be introduced at a far later date.

Again, this setting only affects the INITIAL PHP script file loaded by the interpreter, such as the index.php of Drupal. Files that are included with include, include_once, require, or require_once will be imported as they always have. Files that are included with import are PHP User Modules.

Given that ini settings are frowned upon nowadays, I think having a <?php declare(modules=1); for the initial file might make the idea more likely to pass a vote? Or maybe I’d even try to go one step further and say that whatever file is being executed by SAPI (the first PHP file) could be interpreted with a dumb lookahead. If the file has import / export syntax, treat it like PHP Module, otherwise fallback.

The fun really starts when the from clause shows up.

import foo from "foo.php"

The search order of import is as follows:

  1. Is the file in the same directory as the importing file? Yes, load.
  2. Is there a php_modules directory? If so, is the file in there?
  3. If the importing file is within the tree of the cwd (established by the first file loaded), then recursively look for a php_modules directory until at the cwd until the file is found (this is identical to the seek process of node with it’s analogous node_modules directory
  4. As a final try, consider the PHP include_paths.

I’m not familiar enough with Javascript / Typescript ecosystem, but I’ve only ever seen / used the ability to import using direct filepath. The fact there’s weird behaviors as result of trying to import a file and suddenly a file all the way from include_paths or php_modules seems like a no-go to me. I’d favor using only simple file path navigation and if the file doesn’t exist, error.

Perhaps if the idea gains merit, Composer could offer something similar to Vite where we can create an alias to a specific folder and then import things like from '@package/path/to/file.

This will of course require a package manager similar to composer to become part of core. However, composer will not be eclipsed as the import package manager (phppm?) is only concerned with user modules. These modules must explicitly export any symbols being fetched from them, whereas composer will continue to load files using require.

Imports can also be done against directories

import foo from "mypackage"

In this case the parser will look for “mypackage/index.php”

I’m not fond of this either.

···

Marco Deleu

Perhaps, though a conversation like this is helpful. Some rather complicated RFCs do get approved/voted on before an implementation is done when contributors who are familiar with the Zend engine get on board early. Conversely, there are some extremely thoroughly implemented complicated RFCs that get rejected because most voters don’t participate in discussion until voting is actually started. Something as broad as this probably requires an off-list discussion with key active contributors, because participation on list is so hit-and-miss.

Jordan

···

Marco Deleu

On Thu, Jun 27, 2024 at 1:02 PM MKS Archive <mikeschinkel@gmail.com> wrote:

Interesting to see this. Serendipitous given the email I sent on the list in reply to Larry.

My initial thoughts:

  1. I really like the concept of cleaning up issues that BC make impossible to fix by introducing modules.

Thanks. The sticking point is what degree of change should be occurring. PHP isn’t as behind an 8-ball as JavaScript is since the dev can choose their PHP version and hence deprecation works most of the time for getting rid of old stuff. But not always. Changes that are incompatible with what came before need a way to do things the old way during transition. Again, see PHP 6 and unicode, which snowballed until it was clear that even if PHP 6 had been completed it wouldn’t be able to run most PHP 5 code.

  1. No need for autoloaders with modules; I assume this would be obvious, right?

Depends largely on whether modules can include and require to get access to old code. I also didn’t discuss how they behave - do they share their variables with includes and requires?

  1. Not a good idea to use an ini setting; most view them to be problematic.
  2. .htaccess îs Apache-only, so a non-starter anyway.
  3. The first script should not be a module. If you want that, have a 1 line index.php file do an import.

I love this idea.

  1. Modules should be directories, not .php files. Having each file be a module makes code org really hard.

Yes, but that is how JavaScript currently handles things. It is currently necessary when making large packages to have an index.js that exports out the public members of the module. This entry point is configurable through the package.json of the module.

  1. Modules would have a symbol table metadata file generated by IDEs and during deployment.

Node.js uses package.json and the attendant npm to do this sort of prep work. And it’s a critical part of this since modules can be versioned, and different modules may need to run different specific versions of other modules.

  1. If no metadata file in directory PHP can generate one in memory during first directory access.
  2. .php files in modules as identified by metadata file should not be loadable via HTTP(S).

Those are implementation details a little further down the road than we’re ready for, I think.

  1. Having exports separate from functions and classes seems like it would be problematic.

Again, this is how they work in JavaScript. Not saying that’s the best approach, but even if problematic it’s a solved problem.

  1. Exports could be implemented as attributes, which could be really elegant.
  2. Exports as attributes pairs with the symbol on the line above, and would enable easy aliasing.

Ultimately everything in JavaScript is an object. JavaScript provides a mechanism for handling a module file with a single default export, but it supports multiple exports from the same file which arrive as an object best approximated in PHP as a static class. I could hash out further, but again, I’d like to gauge some interest and very high level feedback. I’m also interested in learning on how other module systems out there do work. I’m picking of JavaScript because most of the PHP community has to use it as well for client side scripting and so most of us should have at least passing familiarity with it.

  1. And finally, when are you starting the RFC? :slight_smile:

It’s too early for anyone to start at this moment - and while I certainly am willing to help I’m not qualified to take the lead on this.

If adopted, this is a massive change, and the results of this conversation won’t hit for years. Let’s take our time. For one, this overarching project will need multiple coordinated RFC’s, as well as figuring out what to do and also in what order.

On Thu, Jun 27, 2024 at 2:11 PM Deleu <deleugyn@gmail.com> wrote:

Who would build it is an extremely key aspect of making changes to PHP. Ideas are hard enough to survive the RFC process when there’s already an implementation. Finding a sponsor to work on this would be the first step.

Agreed.

Given that ini settings are frowned upon nowadays, I think having a <?php declare(modules=1); for the initial file might make the idea more likely to pass a vote? Or maybe I’d even try to go one step further and say that whatever file is being executed by SAPI (the first PHP file) could be interpreted with a dumb lookahead. If the file has import / export syntax, treat it like PHP Module, otherwise fallback.

MKS Archive already pointed out that even this is unecessary. Just let the landing file import the modules, even if that means it’s a one line file.

I’m not familiar enough with Javascript / Typescript ecosystem, but I’ve only ever seen / used the ability to import using direct filepath.

In the clientside up until recently direct filepath was the only way. That changed with import maps

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap

NodeJS has been doing something similar serverside for much longer with CommonJS requires, which predate by a good 5 years the ES6 mechanism. As a serverside language it now has to juggle both.

The resolution path I sketched out is based on how NodeJS works. Can that be improved upon? Likely - it is confusing

The fact there’s weird behaviors as result of trying to import a file and suddenly a file all the way from include_paths or php_modules seems like a no-go to me. I’d favor using only simple file path navigation and if the file doesn’t exist, error.

Perhaps if the idea gains merit, Composer could offer something similar to Vite where we can create an alias to a specific folder and then import things like from '@package/path/to/file.

Composer would need a massive rewrite to be a part of this since it currently requires the file once it determines it should do so. If we do a system where import causes the parser to act differently then that alone means imports can’t be dealt with in the same manner as other autoloads.

This will of course require a package manager similar to composer to become part of core. However, composer will not be eclipsed as the import package manager (phppm?) is only concerned with user modules. These modules must explicitly export any symbols being fetched from them, whereas composer will continue to load files using require.

Imports can also be done against directories

import foo from "mypackage"

In this case the parser will look for “mypackage/index.php”

I’m not fond of this either.

There will need to be a way to define the entrypoint php. I think index.php is reasonable, and if another entry point is desired it can be called out → “mypackage/myentry.php”


Overall, I think PHP has already reached the limit of surviving with only PSR-4 and Composer. Single class files were a great solution to get us out of the nightmare of require and import on top of PHP files. But more than once I have had the desire to declare a couple of interfaces in a single file, or a handful of Enums, etc. It seems like PHP Modules could also address the issue with function autoloading and package-level visibility. I like the idea but I’m a bit skeptical until we have some buy-in from someone that could actually get this implemented.

That would be one of the larger hurdles, if not the largest.

Agreed. I’ve seen both of those occur so I want to avoid both. Even if large sections of the discussion are eventually done off list to avoid getting lost in bike-shed issues, the members of the list, or at least the voting members of the list should be kept updated periodically to prevent the project from going down an unpopular path.

The only thing I’m truly sure about with this is that it will be profoundly difficult to do. But it needs to be addressed because PHP is starting to lag behind in this area.

···

Marco Deleu

On Thu, Jun 27, 2024 at 3:52 PM Jim Winstead <jimw@trainedmonkey.com> wrote:

On Wed, Jun 26, 2024, at 7:15 PM, Michael Morris wrote:

PHP User Modules are php files that are brought into the runtime through a new parser that is able to generate faster and more concise runtime code by removing support for problematic features and imposing a strict mode by default. They focus on PHP as a language and not as a template engine.

I think the problem I have with this proposal is calling these “PHP User Modules”. Here’s an admittedly uncharitable rephrase of this:

"NewLanguage User Modules are NewLanguage…

If you know you’re being insulting why do it? It’s completely unhelpful.

On Wed, Jun 26, 2024, at 7:15 PM, Michael Morris wrote:

PHP User Modules are php files that are brought into the runtime through a new parser that is able to generate faster and more concise runtime code by removing support for problematic features and imposing a strict mode by default. They focus on PHP as a language and not as a template engine.

I think the problem I have with this proposal is calling these “PHP User Modules”. Here’s an admittedly uncharitable rephrase of this:

“NewLanguage User Modules are NewLanguage files that are brought into the PHP runtime through a new parser that may theoretically be able to generate faster and more concise runtime code by implementing a different language based on much of the syntax from PHP. This new language does not prioritize its use as a template language for HTML.”

The only background compatibility break is the introduction of three keywords: “import”, “export” and “from”

“We will add three new keywords to PHP to support accessing variables, classes, and functions implemented in NewLanguage.”

If you got this far, thank you. This overall idea to take one of the better things to happen to JavaScript in the last decade and incorporate it into PHP has been bothering me for awhile so I figured I’d share. I don’t know how much merit there is to this though.

I think there is a lot of ground to be covered in improving PHP’s concept of packages or modules that has largely been punted to user-space with autoloading and Composer and it’s always good to address the seams that has left, but I feel like this proposal, as sketched out so far, reminds me more of what became Raku (from the Perl world) or perhaps Hack than an actual way forward for PHP itself.

Thanks.

Jim

Perhaps my point here wasn’t so obvious. I wasn’t talking about Composer making drastic changes to accommodate this, I was only merely mentioning Composer being used to provide something like the following:

{
"require": {

"php": "^8.2"
....
},
"php-modules": {
"@packages": "./packages",
"@utilities": "./tools/utilities"
....
}
}

Then whenever there’s a import Foo from '@packages/Foo.php', the notation @packages would be replaced by the packages folder. This is equivalent to Vite resolve.alias https://vitejs.dev/config/shared-options.html#resolve-alias

···

Marco Deleu

On Thu, Jun 27, 2024, at 2:14 PM, Jordan LeDoux wrote:

On Thu, Jun 27, 2024 at 12:53 PM Jim Winstead <jimw@trainedmonkey.com> wrote:

On Wed, Jun 26, 2024, at 7:15 PM, Michael Morris wrote:

PHP User Modules are php files that are brought into the runtime through a new parser that is able to generate faster and more concise runtime code by removing support for problematic features and imposing a strict mode by default. They focus on PHP as a language and not as a template engine.

I think the problem I have with this proposal is calling these “PHP User Modules”. Here’s an admittedly uncharitable rephrase of this:

“NewLanguage User Modules are NewLanguage files that are brought into the PHP runtime through a new parser that may theoretically be able to generate faster and more concise runtime code by implementing a different language based on much of the syntax from PHP. This new language does not prioritize its use as a template language for HTML.”

Do you feel that Phar is a separate language? Is PHP no longer PHP if the @ error suppression is removed? I’m really unclear about the point you are making here, even if I ignore the “uncharitable” rephrase.

If I read through the 11 bullet points under “User Module Files” in the original proposal, I see two that are actually related to modules and most of them are just lopping off features from the PHP language in ways both small (no need for <?php) and huge (changing the scoping operator to ‘.’ instead of ‘::’, ‘->’, and '').

The angle I am coming at this from is improving the developer experience around “packages” or “modules” or whatever you want to call them, and so much of this proposal doesn’t seem to be about that.

I could have made that point in other ways, and I’m sorry that my first attempt came off as insulting. It really concerned me when I already saw discussion about taking this off-list and going into the weeds on technical details when the problem that is being addressed by this proposal is extremely unclear to me.

Jim

On Thu, Jun 27, 2024, at 21:23, Michael Morris wrote:

On Thu, Jun 27, 2024 at 1:02 PM MKS Archive <mikeschinkel@gmail.com> wrote:

Interesting to see this. Serendipitous given the email I sent on the list in reply to Larry.

My initial thoughts:

  1. I really like the concept of cleaning up issues that BC make impossible to fix by introducing modules.

Thanks. The sticking point is what degree of change should be occurring. PHP isn’t as behind an 8-ball as JavaScript is since the dev can choose their PHP version and hence deprecation works most of the time for getting rid of old stuff. But not always. Changes that are incompatible with what came before need a way to do things the old way during transition. Again, see PHP 6 and unicode, which snowballed until it was clear that even if PHP 6 had been completed it wouldn’t be able to run most PHP 5 code.

It’s not just up to the dev, but the libraries we use and whether or not we can easily upgrade (or remove) them to upgrade the php version.

  1. No need for autoloaders with modules; I assume this would be obvious, right?

Depends largely on whether modules can include and require to get access to old code. I also didn’t discuss how they behave - do they share their variables with includes and requires?

I think it would be a mistake to exclude old code and/or prevent templating. Not only are there now decades old code in some orgs, but how would you write an email sender that sent templated emails, provide html, generate code, etc? There has to be an output from the code to be useful.

  1. Not a good idea to use an ini setting; most view them to be problematic.

  2. .htaccess îs Apache-only, so a non-starter anyway.

  3. The first script should not be a module. If you want that, have a 1 line index.php file do an import.

I love this idea.

  1. Modules should be directories, not .php files. Having each file be a module makes code org really hard.

Yes, but that is how JavaScript currently handles things. It is currently necessary when making large packages to have an index.js that exports out the public members of the module. This entry point is configurable through the package.json of the module.

I think it’s fine to use js as an inspiration, but it isn’t the only one out there. There is some precedent to consider directories as modules (go calls them “packages”) and especially in PHP where namespaces (due to PSR-4 autoloading) typically match directory structures.

For example, I’m still going to go forward with my #[Internal] attribute RFC some time in the next month or so, which will be namespace based. I have no idea if it will pass, (some people are worried about it clashing with an RFC like this one) but I think we’d have value in it for years to come until something like this gets fleshed out. We will see…

  1. Modules would have a symbol table metadata file generated by IDEs and during deployment.

Node.js uses package.json and the attendant npm to do this sort of prep work. And it’s a critical part of this since modules can be versioned, and different modules may need to run different specific versions of other modules.

Please, please, please do not make a json file a configuration language. You can’t comment in them, you can’t handle “if php version <9, load this, or if this extension is installed, use this.”

Maybe that is desirable, but doing things slightly different based on extensions loaded is def a thing.

  1. If no metadata file in directory PHP can generate one in memory during first directory access.

  2. .php files in modules as identified by metadata file should not be loadable via HTTP(S).

Those are implementation details a little further down the road than we’re ready for, I think.

Personally, if these are going to have any special syntax, we probably shouldn’t call them .php files. Maybe .phm?

  1. Having exports separate from functions and classes seems like it would be problematic.

Again, this is how they work in JavaScript. Not saying that’s the best approach, but even if problematic it’s a solved problem.

the only thing I don’t like about this import/export thing is that it reminds me of the days when we had to carefully order our require_once directives to make sure files were loaded before they were used. So, I think it is worth thinking about how loading will work and whether loading can be dynamic, hoisted out of function calls (like js), how order matters, whether packages can enrich other packages (like doctrine packages) and if so, how much they can gain access to internal state, etc. This is very much not “a solved problem.”

  1. Exports could be implemented as attributes, which could be really elegant.

  2. Exports as attributes pairs with the symbol on the line above, and would enable easy aliasing.

Ultimately everything in JavaScript is an object. JavaScript provides a mechanism for handling a module file with a single default export, but it supports multiple exports from the same file which arrive as an object best approximated in PHP as a static class. I could hash out further, but again, I’d like to gauge some interest and very high level feedback. I’m also interested in learning on how other module systems out there do work. I’m picking of JavaScript because most of the PHP community has to use it as well for client side scripting and so most of us should have at least passing familiarity with it.

In JavaScript, arrays are instances, in php, they are values. This is something to consider if a module exports an array of exports.

  1. And finally, when are you starting the RFC? :slight_smile:

It’s too early for anyone to start at this moment - and while I certainly am willing to help I’m not qualified to take the lead on this.

If adopted, this is a massive change, and the results of this conversation won’t hit for years. Let’s take our time. For one, this overarching project will need multiple coordinated RFC’s, as well as figuring out what to do and also in what order.

— Rob

On Thu, Jun 27, 2024 at 12:53 PM Jim Winstead <jimw@trainedmonkey.com> wrote:

On Wed, Jun 26, 2024, at 7:15 PM, Michael Morris wrote:

PHP User Modules are php files that are brought into the runtime through a new parser that is able to generate faster and more concise runtime code by removing support for problematic features and imposing a strict mode by default. They focus on PHP as a language and not as a template engine.

I think the problem I have with this proposal is calling these “PHP User Modules”. Here’s an admittedly uncharitable rephrase of this:

“NewLanguage User Modules are NewLanguage files that are brought into the PHP runtime through a new parser that may theoretically be able to generate faster and more concise runtime code by implementing a different language based on much of the syntax from PHP. This new language does not prioritize its use as a template language for HTML.”

Do you feel that Phar is a separate language? Is PHP no longer PHP if the @ error suppression is removed? I’m really unclear about the point you are making here, even if I ignore the “uncharitable” rephrase.

Jordan

On Thu, Jun 27, 2024 at 4:55 PM Rob Landers rob@bottled.codes wrote:

On Thu, Jun 27, 2024, at 21:23, Michael Morris wrote:

On Thu, Jun 27, 2024 at 1:02 PM MKS Archive <mikeschinkel@gmail.com> wrote:

Interesting to see this. Serendipitous given the email I sent on the list in reply to Larry.

My initial thoughts:

  1. I really like the concept of cleaning up issues that BC make impossible to fix by introducing modules.

Thanks. The sticking point is what degree of change should be occurring. PHP isn’t as behind an 8-ball as JavaScript is since the dev can choose their PHP version and hence deprecation works most of the time for getting rid of old stuff. But not always. Changes that are incompatible with what came before need a way to do things the old way during transition. Again, see PHP 6 and unicode, which snowballed until it was clear that even if PHP 6 had been completed it wouldn’t be able to run most PHP 5 code.

It’s not just up to the dev, but the libraries we use and whether or not we can easily upgrade (or remove) them to upgrade the php version.

  1. No need for autoloaders with modules; I assume this would be obvious, right?

Depends largely on whether modules can include and require to get access to old code. I also didn’t discuss how they behave - do they share their variables with includes and requires?

I think it would be a mistake to exclude old code and/or prevent templating. Not only are there now decades old code in some orgs, but how would you write an email sender that sent templated emails, provide html, generate code, etc? There has to be an output from the code to be useful.

  1. Not a good idea to use an ini setting; most view them to be problematic.

  2. .htaccess îs Apache-only, so a non-starter anyway.

  3. The first script should not be a module. If you want that, have a 1 line index.php file do an import.

I love this idea.

Going to come back to this actually.

For example, I’m still going to go forward with my #[Internal] attribute RFC some time in the next month or so, which will be namespace based. I have no idea if it will pass, (some people are worried about it clashing with an RFC like this one) but I think we’d have value in it for years to come until something like this gets fleshed out. We will see…

What about declare? I have no idea if this would work, but…

declare(importmap=[
‘imports’ => [
‘label’ : ‘path’,
]
]

If that is put in the initial php file then it could map out the imports. An IDE could maintain the file as well. The other two attributes are scopes and integrity - the latter being a hash check for the file, scopes could be used to handle php version numbers. Multiple import maps could be defined, with each map affecting the file and whatever it imports - the seek order moving up.

It would be possible to let import maps affect include and require as well. Would there be a benefit? Or just more confusion?

  1. Modules would have a symbol table metadata file generated by IDEs and during deployment.

Node.js uses package.json and the attendant npm to do this sort of prep work. And it’s a critical part of this since modules can be versioned, and different modules may need to run different specific versions of other modules.

Please, please, please do not make a json file a configuration language. You can’t comment in them, you can’t handle “if php version <9, load this, or if this extension is installed, use this.”

Lack of comments are a problem. NodeJS does handle engine blocks, but it’s messy. That said, I’m not a fan of json’s popularity even in Javascript, and less so in PHP where it feels foreign.

Maybe that is desirable, but doing things slightly different based on extensions loaded is def a thing.

Keep in mind that extensions typically expose functions automatically, and under the original proposal those functions have to be imported to be used: import mysql_query

Perhaps PHP imports, unlike their JavaScript or even Java C# counterparts, could be placed in try/catch blocks, with the catch resolving what to do if the import misses.

  1. If no metadata file in directory PHP can generate one in memory during first directory access.

  2. .php files in modules as identified by metadata file should not be loadable via HTTP(S).

Those are implementation details a little further down the road than we’re ready for, I think.

Personally, if these are going to have any special syntax, we probably shouldn’t call them .php files. Maybe .phm?

I really don’t like the extension games seen in node with js, cjs and mjs, but there’s a precedent for doing it that way. In their setup if you’ve set modules as the default parse method then cjs can be used to identify files that still need to use CommonJS. And mjs can force the ES6 even in default mode. But it is a bit of a pain and feels like it should be avoided.

the only thing I don’t like about this import/export thing is that it reminds me of the days when we had to carefully order our require_once directives to make sure files were loaded before they were used. So, I think it is worth thinking about how loading will work and whether loading can be dynamic, hoisted out of function calls (like js), how order matters, whether packages can enrich other packages (like doctrine packages) and if so, how much they can gain access to internal state, etc. This is very much not “a solved problem.”

In JavaScript import must be top of the file - you’ll get an error if you try an import following any other statement unless it’s a dynamic import(), which is a whole other Promise/Async/Kettle of fish that thankfully PHP does not have to take into account as, until you get used to it (and even after), async code is a headache.

In JavaScript, arrays are instances, in php, they are values. This is something to consider if a module exports an array of exports.

import() (a different animal from import, yes, that is confusing, yay JavaScript) returns a promise which resolves to an object. I’ve slammed my head into a desk more than once over this, and it’s a feature I don’t want brought in.

On Thu, Jun 27, 2024 at 2:41 PM Jim Winstead <jimw@trainedmonkey.com> wrote:

On Thu, Jun 27, 2024, at 2:14 PM, Jordan LeDoux wrote:

On Thu, Jun 27, 2024 at 12:53 PM Jim Winstead <jimw@trainedmonkey.com> wrote:

On Wed, Jun 26, 2024, at 7:15 PM, Michael Morris wrote:

PHP User Modules are php files that are brought into the runtime through a new parser that is able to generate faster and more concise runtime code by removing support for problematic features and imposing a strict mode by default. They focus on PHP as a language and not as a template engine.

I think the problem I have with this proposal is calling these “PHP User Modules”. Here’s an admittedly uncharitable rephrase of this:

“NewLanguage User Modules are NewLanguage files that are brought into the PHP runtime through a new parser that may theoretically be able to generate faster and more concise runtime code by implementing a different language based on much of the syntax from PHP. This new language does not prioritize its use as a template language for HTML.”

Do you feel that Phar is a separate language? Is PHP no longer PHP if the @ error suppression is removed? I’m really unclear about the point you are making here, even if I ignore the “uncharitable” rephrase.

If I read through the 11 bullet points under “User Module Files” in the original proposal, I see two that are actually related to modules and most of them are just lopping off features from the PHP language in ways both small (no need for <?php) and huge (changing the scoping operator to ‘.’ instead of ‘::’, ‘->’, and '').

The angle I am coming at this from is improving the developer experience around “packages” or “modules” or whatever you want to call them, and so much of this proposal doesn’t seem to be about that.

I could have made that point in other ways, and I’m sorry that my first attempt came off as insulting. It really concerned me when I already saw discussion about taking this off-list and going into the weeds on technical details when the problem that is being addressed by this proposal is extremely unclear to me.

Jim

Ah, yes, THAT’S a fair point. While the idea of optimizing the engine/parser for modules has merit as part of a user modules proposal, I agree that many of the specifics proposed here feel pretty scatter-shot and unclear.

The scoping operator change I simply ignored, as that feels to me like just asking “I would like to program in Node” and there’s no clear benefit to changing the scoping operator outlined, while there is a clear detriment to eliminating the concatenation operator entirely.

Mostly I ignored that aspect of it, because I assumed that all the people capable of implementing this proposal would just refuse stuff like that outright, and that the inclusion of it would guarantee the RFC fails, so no point in worrying.

But the broader question you are presenting about the focus and goals of the proposal, and how the specifics relate to that, is actually a question that I share.

Jordan

On Thu, Jun 27, 2024, at 23:24, Michael Morris wrote:

On Thu, Jun 27, 2024 at 4:55 PM Rob Landers rob@bottled.codes wrote:

On Thu, Jun 27, 2024, at 21:23, Michael Morris wrote:

On Thu, Jun 27, 2024 at 1:02 PM MKS Archive <mikeschinkel@gmail.com> wrote:

Interesting to see this. Serendipitous given the email I sent on the list in reply to Larry.

My initial thoughts:

  1. I really like the concept of cleaning up issues that BC make impossible to fix by introducing modules.

Thanks. The sticking point is what degree of change should be occurring. PHP isn’t as behind an 8-ball as JavaScript is since the dev can choose their PHP version and hence deprecation works most of the time for getting rid of old stuff. But not always. Changes that are incompatible with what came before need a way to do things the old way during transition. Again, see PHP 6 and unicode, which snowballed until it was clear that even if PHP 6 had been completed it wouldn’t be able to run most PHP 5 code.

It’s not just up to the dev, but the libraries we use and whether or not we can easily upgrade (or remove) them to upgrade the php version.

  1. No need for autoloaders with modules; I assume this would be obvious, right?

Depends largely on whether modules can include and require to get access to old code. I also didn’t discuss how they behave - do they share their variables with includes and requires?

I think it would be a mistake to exclude old code and/or prevent templating. Not only are there now decades old code in some orgs, but how would you write an email sender that sent templated emails, provide html, generate code, etc? There has to be an output from the code to be useful.

  1. Not a good idea to use an ini setting; most view them to be problematic.

  2. .htaccess îs Apache-only, so a non-starter anyway.

  3. The first script should not be a module. If you want that, have a 1 line index.php file do an import.

I love this idea.

Going to come back to this actually.

For example, I’m still going to go forward with my #[Internal] attribute RFC some time in the next month or so, which will be namespace based. I have no idea if it will pass, (some people are worried about it clashing with an RFC like this one) but I think we’d have value in it for years to come until something like this gets fleshed out. We will see…

What about declare? I have no idea if this would work, but…

declare(importmap=[

‘imports’ => [

‘label’ : ‘path’,

]

]

If that is put in the initial php file then it could map out the imports. An IDE could maintain the file as well. The other two attributes are scopes and integrity - the latter being a hash check for the file, scopes could be used to handle php version numbers. Multiple import maps could be defined, with each map affecting the file and whatever it imports - the seek order moving up.

It would be possible to let import maps affect include and require as well. Would there be a benefit? Or just more confusion?

Internals has made it pretty clear: no more declare or ini entries (unless it is absolutely needed).

I personally don’t like it because it uses arrays, which are opaque, easy to typo, and hard to document/check.

Instead, maybe consider a new Reflection API?

(new ReflectionModule)->import(‘MyModule’)->run()

From the index.php file (where “run” is an exported function and can take arguments, like $argv, request objects, globals, etc).

Inside modules, we would have the import syntax (which could arguably be compiled to the above code, more-or-less).

  1. Modules would have a symbol table metadata file generated by IDEs and during deployment.

Node.js uses package.json and the attendant npm to do this sort of prep work. And it’s a critical part of this since modules can be versioned, and different modules may need to run different specific versions of other modules.

Please, please, please do not make a json file a configuration language. You can’t comment in them, you can’t handle “if php version <9, load this, or if this extension is installed, use this.”

Lack of comments are a problem. NodeJS does handle engine blocks, but it’s messy. That said, I’m not a fan of json’s popularity even in Javascript, and less so in PHP where it feels foreign.

Maybe that is desirable, but doing things slightly different based on extensions loaded is def a thing.

Keep in mind that extensions typically expose functions automatically, and under the original proposal those functions have to be imported to be used: import mysql_query

they also do now, unless you either prefix them with \ or rely on the fallback resolution system. I’m honestly not sure we need a new syntax for this, but maybe just disable the global fallback system in modules?

Perhaps PHP imports, unlike their JavaScript or even Java C# counterparts, could be placed in try/catch blocks, with the catch resolving what to do if the import misses.

Right now, I usually see if(function_exists(‘some_func_from_extension’)), so as long as imports behave as they currently do — not actually triggering any loading — then this would still work just fine.

  1. If no metadata file in directory PHP can generate one in memory during first directory access.

  2. .php files in modules as identified by metadata file should not be loadable via HTTP(S).

Those are implementation details a little further down the road than we’re ready for, I think.

Personally, if these are going to have any special syntax, we probably shouldn’t call them .php files. Maybe .phm?

I really don’t like the extension games seen in node with js, cjs and mjs, but there’s a precedent for doing it that way. In their setup if you’ve set modules as the default parse method then cjs can be used to identify files that still need to use CommonJS. And mjs can force the ES6 even in default mode. But it is a bit of a pain and feels like it should be avoided.

I would argue that it be something seriously considered. Scanning a directory in the terminal, in production systems, while diagnosing ongoing production issues, it can be very handy to distinguish between the “old way” and “new way”, at a glance.

the only thing I don’t like about this import/export thing is that it reminds me of the days when we had to carefully order our require_once directives to make sure files were loaded before they were used. So, I think it is worth thinking about how loading will work and whether loading can be dynamic, hoisted out of function calls (like js), how order matters, whether packages can enrich other packages (like doctrine packages) and if so, how much they can gain access to internal state, etc. This is very much not “a solved problem.”

In JavaScript import must be top of the file - you’ll get an error if you try an import following any other statement unless it’s a dynamic import(), which is a whole other Promise/Async/Kettle of fish that thankfully PHP does not have to take into account as, until you get used to it (and even after), async code is a headache.

Are you sure? I don’t remember them removing import hoisting, but it’s probably more of a typical linting rule because it is hard to reason about.

https://www.w3schools.com/js/js_hoisting.asp

In other news, async in PHP is alive and well. Fibers are a thing and swoole just announced threading.

In JavaScript, arrays are instances, in php, they are values. This is something to consider if a module exports an array of exports.

import() (a different animal from import, yes, that is confusing, yay JavaScript) returns a promise which resolves to an object. I’ve slammed my head into a desk more than once over this, and it’s a feature I don’t want brought in.

— Rob

On 27/06/2024 03:15, Michael Morris wrote:

If you got this far, thank you. This overall idea to take one of the better things to happen to JavaScript in the last decade and incorporate it into PHP has been bothering me for awhile so I figured I'd share. I don't know how much merit there is to this though.

Thank you for sharing. I think it's valuable to explore radical ideas sometimes.

I do think PHP badly needs a native concept of "module" or "package" - in fact, I'm increasingly convinced it's the inevitable path we'll end up on at some point. BUT I think any such concept needs to be built on top of what we have right now. That means:

- It should build on or work in harmony with namespaces, not ignore or replace them
- It should be compatible with Composer, but not dependent on it
- It should be easy to take existing code, and convert it to a module/package
- It should be easy to carry on using that module/package after it's been converted

If we can learn from other languages while we do that, I'm all for it; but we have to remember that those languages had a completely different set of constraints to work with.

For instance, JS has no concept of "namespaces", but does treat function names as dynamically scoped alongside variables. So the module system needed to give a way of managing how you imported names from one scope to another. That's not something PHP needs, because it treats all names as global, and namespaces have proved an extremely successful way of sharing code without those names colliding.

Other parts of your e-mail are essentially an unrelated idea, to have some new "PHP++" dialect, where a bunch of "bad" things are removed. You're not the first person to be tempted by this, but I think the history HHVM and Hack is educational here: initially, PHP and Hack were designed to interoperate on one run-time, but the more they tried to optimise for Hack, the harder it became to support PHP, and now Hack is a completely independent language.

I'm not even sure what problem some of your ideas are intended to solve, e.g. using "." instead of "::" and "->". At that point, it really does feel like you just want to create a new language, mixing ideas from PHP and JS, but incompatible with either of them.

I do hope this discussion can inspire some interesting ideas, but I don't think what you've presented is the right way to go.

Regards,

--
Rowan Tommins
[IMSoP]

On Thu, Jun 27, 2024, at 2:15 AM, Michael Morris wrote:

If you got this far, thank you. This overall idea to take one of the
better things to happen to JavaScript in the last decade and
incorporate it into PHP has been bothering me for awhile so I figured
I'd share. I don't know how much merit there is to this though.

There's a lot to chew on here, and some interesting ideas. However, reading through it, there's one key question that sticks in my mind:

What problem is this trying to solve?

What problem would packages/modules/whatever be solving that isn't already adequately solved?

There seems to be a bunch of stuff kinda-sorta being addressed in this proposal, but no clear picture of the problem being solved, and how it gets solved.

Before we get anywhere close to weeds, there's high-level questions that need to be answered.

Which of these are we trying to solve? (Solving all of them at once is unlikely, and some are mutually-incompatible.)

1. Adding a "strict pedantic mode" without messing with existing code?
2. Package-level visibility (public, package, protected, private)?
3. Avoid name clashes?
4. Improved information for autoloaders and preloading, possibly making class-per-file unnecessary in many cases?
5. A larger scope for the compiler to analyze in order to make optimizations?
6. Package-level declares, inherited by all files in the package?
7. Something else?

We need to know exactly what we're solving for to be able to determine if a proposal is any good at solving it.

For me personally, 2 and 4 would be the main things to address, and if someone with more compiler knowledge than me could do something on 5, that would be neat. 3 is, as Tim noted, a solved problem at this point. 1 we already are working on in stages via deprecations. 6 is potentially unwise, unless we had a good set of things that made sense to specify at a package level.

Once we know what we're trying to solve, we need to ask about constraints. The major one being the relationship with namespaces.

Do we want:

1. Packages and namespaces are synonymous? (This is roughly how JVM languages work, I believe.)
2. Packages and files are synonymous? (This is how Python and Javascript work.)
3. All packages correspond to a namespace, but not all namespaces are a package?

And given the near-universality of PSR-4 file structure, what impact would each of those have in practice? (Even if packages open up some new autoloading options and FIG publishes a new PSR for how to use them, there's only a billion or so PSR-4 class files in the wild that aren't going away any time soon.) My gut feeling is we want 3, but I'm sure there's a debate to be had there.

All the other stuff about different operators and file name extensions and stuff is completely irrelevant until there is a solid consensus on these basic questions. For something of this scale, to coin a phrase, "bring me problems, not solutions."

--Larry Garfield