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