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.mich...@gmail.com.  Is it possible to unsubscribe that email?

Reply via email to