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

From: Date: Thu, 27 Jun 2024 21:56:10 +0000
Subject: Re: Fwd: [PHP-DEV] [Initial Feedback] PHP User Modules - An Adaptation of ES6 from JavaScript
References: 1 2 3 4 5 6  Groups: php.internals 
Request: Send a blank email to [email protected] to get a copy of this message


On Thu, Jun 27, 2024, at 23:24, Michael Morris wrote:
> 
> 
> On Thu, Jun 27, 2024 at 4:55 PM Rob Landers <[email protected]> wrote:
>> __
>> On Thu, Jun 27, 2024, at 21:23, Michael Morris wrote:
>>> 
>>> On Thu, Jun 27, 2024 at 1:02 PM MKS Archive <[email protected]> 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.
>> 
>>>  
>>>> 2. 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.. 
>> 
>>>  
>>>> 
>>>> 3. Not a good idea to use an ini setting; most view them to be problematic.
>>>> 4. .htaccess îs Apache-only, so a non-starter anyway.
>>>> 5. 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). 

>  
>> 
>>>  
>>>> 7. 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.. 

>  
>> 
>>>  
>>>> 8. If no metadata file in directory PHP can generate one in memory during first
>>>> directory access. 
>>>> 9. .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


Thread (4 messages)

« previous php.internals (#123974) next »