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