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