> On Jul 9, 2024, at 1:15 PM, Larry Garfield <la...@garfieldtech.com> wrote: > On Sat, Jul 6, 2024, at 1:12 AM, Mike Schinkel wrote: >> WordPress differs from the apps many *(most?)* developers on PHP >> Internals work with in the following way: >> >> WordPress = *User-managed app* >> Most = *Developer-managed apps* >> >> In a* Developer-Managed app* developers choose which 3rd party >> functionality will be incorporated into their sites whereas with a >> *User-managed app* users choose which 3rd party functionality will be >> incorporated into their site. And that is the KEY difference. >> >> So I am wondering if we can get people on this PHP Internals list who >> dismiss the needs of WordPress developer BECAUSE it is WordPress to >> recognize that User-Managed apps ARE a class of PHP applications have >> needs that **deserve** to be addressed? >> * >> * >> Two (2)* unmet needs of User-Managed apps *that *"standard" *PHP >> currently does not address come to mind: >> >> User-managed apps needs to be able to handle both: >> * >> * >> 1. *User-added add-ons* *("plugins" in WordPress, "modules" in Drupal) >> *that have conflicting dependencies, and >> >> 2. *Add-on directory structures *that do not follow a PSR-4 directory >> hierarchy. >> >> As for #2, even if those apps could rearchitect their existing >> directory structure they cannot realistically be expected to do with >> because of the huge BC issues their users would experience. >> >> And newly created User-managed apps may still find that a PSR-4 >> directory structure is not in the best interest of their project or >> their users. To elaborate, PSR-4 generally assumes that ALL code goes >> into ONE hierarchy and that any and all code that will be autoload gets >> placed in that hierarchy. >> >> But with add-ons it makes a lot more sense to have the entire add-on >> contained in its own add-on directory. This is exactly where PSR-4 >> breaks down with respect to User-managed apps. >> >> Sure, you can have multiple PSR-4 autoloader root directories, but that >> does not scale well to websites with a large number of add-ons as many >> WordPress sites I worked on used. Some had over 100 plugins. With a >> hierarchy of autoloader maps that Michael Morris is proposing WordPress >> could collect up all the maps and create one map every time a plugin is >> added, updated or deleted. >> >> </epiphany> > > I am going to jump in here on this point specifically, because it seems to be > a mix of genuinely insightful observation (though not unique) and uninformed > FUD. > > Some context: I haven't seriously used Wordpress in, ever. However, I was a > Drupal lead developer for many years, and wrote, among other things, Drupal's > DBAL, Drupal's first autoloader, Drupal's PSR-3 implementation, was involved > in Drupal's file organization guidelines for Drupal 8+ (when Drupal adopted a > PSR-0/4 autoloader), and led the Drupal 8 "Modernize all the things" effort. > So I do have some non-trivial experience in this area.
Yes. I remember that about you as well, Crell. > First, you're correct that there is an architectural difference between > "projects that assume the owner has CLI access" and those that do not. You > are also correct that most of the Internals crowd comes from the former. > > However, I don't think it's fair to say that's why Internals folks "dismiss" > Wordpress generally. No, I said you dismiss the concerns of user-managed apps *because* you dismiss WordPress, which we know because you just gave a list of why you dismiss WordPress. What I was hoping was to make the distinction that user-managed apps — regardless of if they are WordPress, are some other user-managed app — have needs that are unfair to demonize simply because you have contempt for the poster-child of user-managed apps. > And yes, I fully agree that any module/package/thing needs to take into > account the needs of both types of projects. As Rowan has repeated, that > means keeping the impact of any changes minimal, so that the Composer > ecosystem and WP ecosystem can TYPO3 ecosystem can build their own tooling on > top of it. > > You'll note I did not list Drupal there. That's because modern Drupal is > composer-based, and has been for many years. I was the one that pushed hard > for adopting Composer, its autoloader, and PSR-4 for Drupal 8 in the first > place. While much of the transition happened after I left the project, the > groundwork is over a decade old. Composer is the preferred way to use > Drupal, and to install Drupal modules. Interesting regarding Drupal 8 and beyond. The ONE place where I will accept your claims that my comments have been "uninformed" and/or "ignorant" has been WRT the details of using Drupal 8+ and beyond. BTW, based on your comments about Drupal and my subsequent analysis it turns out that Drupal is now much more of a developer-managed app than a user-managed app. I started my PHP career on Drupal in 2008 and worked with it for two years until the work dried up and I had to switch to WordPress. I later found a paying Drupal project but after two weeks I fired myself because working with Drupal was such a pain compared to working with WordPress (long story, but basically it came down to theming architectures — Drupal's was coupled vs. WordPress' being decoupled — making Drupal much harder to theme when compared to WordPress.) Interesting that Drupal 8+ fully embraced PSR-4. I was aware of their embrace of Symfony in Drupal 8 and even wrote a blog post[1] right at 10 years ago on how that decision would result in a sizable decline in Drupal's user base over time. I drew on my experience watching the precipitous decline of Visual Basic when Microsoft transitioned from Visual Basic 6 to VB.NET — and history shows I was right about Drupal, at least in predicting the sizable market decline. Visual Basic was once the most widely-used programming language in the world. But after moving to VB.NET it fell into almost complete obscurity. In the past decade Drupal's marketshare of CMS has fallen significantly, from around 7.2% of CMS in Jan 2013 to 1.4% in July 2024. Of course there are far too many factors to say Drupal's decline was in-fact because of their embrace of complexity but it certainly correlates. A more charitable analysis is that Drupal chose to go upmarket to the enterprise which needed that complexity, but that would also imply that the rest of the market moved on from Drupal likely because the complexity no longer met their needs. #fwiw > So the line is not as hard between those two models as you might think. > >> PSR-4 generally assumes that ALL code goes >> into ONE hierarchy and that any and all code that will be autoload gets >> placed in that hierarchy. > > This is flatly untrue, and belies a considerable ignorance about how PSR-4 > and Composer work. No, It shows that you ignored my use of the word "generally." And the only thing it belies is that you chose the *least* charitable characterization of my knowledge of how PSR-4 and Composer work that you could have, instead of charitably presuming that maybe I actually do have valuable insight you do not have. I do not presume the same of you — knowing you have knowledge I do no have in various areas. I do however make exception for those areas where you both claim a lack of experience and then demonstrate a lack of knowledge, as I reveal in sections below. Btw, if I revised my words to avoid being imprecise with "generally" I would write that PHP encourages **too many** autoloader callbacks, and the way most of the PHP community tries to manage that is to condense all those independent groups of code each with their own autoloader callback, down into as few PSR-4 hierarchies that with as few autoloader callbacks as possible. Just like procedural __get and __set magic methods seemed like a good idea at the time but now declarative property hooks will supplant them so to I argue that procedural autoloaders — which seemed like a good idea at the time — have the same types of issues as procedural magic methods and that moving to a declarative form for autoloading would improve PHP significantly. > PHP supports multiple autoloader callbacks, and has for over 15 years. You > absolutely can register multiple if you'd like, using whatever logic you > like. PHP will call each one in turn until the class is loaded. Of *course* PHP supports multiple autoloader callbacks. I know, I had to work with many autoloaders over the years of developing WordPress sites and plugins. But PHP supporting multiple autoloader callbacks is far from the benefit you are insinuating when they proliferate. Consider a user-managed WordPress site — and I worked on many like this after the site had gotten so slow the user had to hire a developer — where the user has 50+ active plugins on the site. And then consider that up to 51 autoloaders had been registered, or on average 25 autoloaders run EVERY new symbol load attempt which results in a performance and complexity nightmare. So if there is ignorance in this thread, it is the blissful ignorance of the issues that too many autoloader callbacks can cause. And that ignorance from someone who directly claims "I haven't seriously used Wordpress in, ever." So please let us both acknowledge what each of us *do* know vs. what we do not, and then accept that the *other* likely has insight into the areas the opposite person does not know. > All PSR-4 does is specify a directory structure that makes a common > autoloader stupidly simple to write. It's just a few lines long. But you > can already do any logic you like for an autoloader. PHP doesn't care. > > However, nothing precludes you from registering multiple autoloaders, all > using PSR-4, all using a different path root. That has been trivially simple > to do since 2009. (OK, it was PSR-0 at the time, but the implications here > are the same.) So your statement above about "all code goes into one > hierarchy" is simply flat out false. > > Of course, as you note, registering lots of separate autoloaders has a > performance impact. That is true. Which is why I don't think anyone > actually does that. No one, well, except everyone who writes a plugin for WordPress. And in production, except everyone who runs multiple plugins, which is practically everyone who runs a WordPress site. Again, your admitted lack of ever using WordPress is showing your lack of experience on this topic. > Composer, for instance, registers a single autoloader only. That autoloader > internally tracks many dozens of PSR-4 roots (one for each package, sometimes > two per package), as well as files that will get force-loaded when the > autoloader is registered, plus generated classmaps. > > Using class maps, you can put a hundred classes in one file and composer can > handle that *today*. That has always been possible. That no one does so is > a sign that there's little reason to do so in most cases. What is your evidence of your claim that "no one does so?" I just pulled up the source for one my most recently WordPress clients — the first one I looked at since your email — and searched for `spl_autoload_register(" in the `/wp-content/plugins/` directory. I found 43 different autoloaders being registered. Here is a screenshot of that: https://postimg.cc/TyWjW6Px So clearly yes, "people do so." And many of them do. True, they are not inside the bubble where you reside, a bubble where no other residents do that either. But outside that bubble the practice is widespread as there is not a better way that is also realistic for the individual site builder to choose. > In fact, if you use an optimized/dumped autoloader, then Composer simply > builds an internal giant lookup table of what class maps to what file. PSR-4 > is then *completely irrelevant* at runtime. It's already one giant O(1) > lookup map. That can be done *today*. That *is* done today. Yes, it can be done today. It *is* done today. By. Developer. Managed. Apps. > But what about systems like Drupal, that don't put code in `/vendor/`? > Drupal ties directly into Composer via its API,and has done so for a decade. > Drupal, a "user-managed application" as you describe it, has Composer baked > in at a core level. > > It looks like the integration has evolved considerably since I was last > involved, but have a look at: > > https://git.drupalcode.org/project/drupal/-/tree/11.x/composer Like I previously said, if the team managing a project does not care about BC — as Drupal apparently did not in its transition to Composer — then tying Composer into the core is not a problem. But if they DO care about BC — as WordPress very much cares about — then fully integrating Composer into an existing user-managed app is a non-starter. And as Drupal's decline in user base over the past decade shows, doing so also which carries a high level of risk of shedding user base, too. > As of when I last looked at it (around 2016 or so), Drupal registers its > module code roots with Composer directly, and then Composer takes over from > there and integrates Drupal's code into its own indexes. There is still only > one single autoloader registered with PHP. This is entirely fine. Yes, as the Drupal module Ludwig[3] explains. It can be managed by a Drupal module, but even its own authors do not recommend doing so, stating (parenthetical mine): "However, please note that Composer (on the CLI) is highly recommended whenever possible!" Which again, means current Drupal is now effectively a developer-managed app. > I would encourage you to do your research before speaking > pseudo-authoritatively on this topic, as you clearly are mis-stating both the > problem and the tools involved today. Back at you; see the above. > What Drupal does not do is address the "different dependency version" > question. And neither does Wordpress. Or TYPO3. Or any other project. > Because that's a core PHP limitation. That too. > PHP works very very differently. PHP has a single global list of symbols. > (Well, two, for classes and functions.) Namespaces are just syntax sugar > over very-long-names, nothing more. There is no "local symbol table," so > having different local symbol tables point to different code blocks using the > same name is not even conceivable. > > If you want to change that, and give PHP multiple local symbol tables, then > autoloading... is utterly irrelevant. The question there is "how can we > introduce local symbol tables in the engine without requiring 10 million > developers to rewrite the file header of 1 billion PHP files across the > world?" You have not shown how having a local symbol table "requires 10 million developer to rewrite header files..." As I envision it, no such thing would be required. However, maybe I just do not understand enough about how PHP internals currently works? How about explaining your assertion that a local symbol table requires a rewrite of all PHP file's header? > Honestly, I'm not convinced its even possible. Someone with more engine > knowledge than I could be able to find away, maybe, but I am skeptical. If > it's even possible, I suspect it would be an absurdly large amount of work > and necessarily include many hard BC breaks. > > If you'd like to prove me wrong, go for it. But that's the problem to > address. Debating file paths is about four steps down the line before it's > even relevant. And even then... if you can't make a PSR-4-organized package > (of which there are several hundred thousand) slot into that new model > comfortably with zero effort on the part of the package author, it's doomed. Now is a good time to summarize the request that you claim is "4 steps down the line" that I (and maybe Michael Morris?) wants to get PHP to incorporate, at least as I see it. The request is to add class maps with a PHP-standardized format into PHP core so that when a library of code needs to register classes to be autoloaded they can contribute to a cascading of class maps where ONE internal function checks the single union of all class maps for a mapped symbol before turning over control if no such symbol is found in the map to the procedural autoloaders that are currently available. That way *any* PHP code could register its own class map without having to get the core app to rearchitect itself to allow that to happen. It is really as simple as that, and the duplicate symbol issue is orthogonal, but relating them can see synergy in implementation. > So please, spare us the ill-informed descriptions of how you think > autoloaders work, when you have demonstrated you do not know how they work. > > Spare us the litany of complaints about PSR-4 when you have demonstrated you > don't know what PSR-4 says. No, spare me your bad-faith accusations of ignorance — I demonstrated my knowledge above — and your claims that "nobody is doing" exactly what I illustrated above that they are doing. > Spare us the gnashing of teeth about how hard it is to use a Wordpress plugin > that hasn't been updated in 10 years with a modern plugin because the former > is still using a 10 year old abandoned version of some library, when that's > not PHP's problem, that's a Wordpress maintenance problem. Again, showing that your contempt of WordPress is allowing you to dismiss the needs of all user-manage apps as being "a maintenance problem." > If you want to move this effort forward, here's your todo list: > > 1. Do some research in the engine to determine if local symbol tables are > even possible without rewriting the engine. Will do. > 2. Work through the highly complex logic of handling three layer overlapping > transitive dependencies in a diamond pattern with conflicting version > requirements. Why? I do not see that as a problem that needs to be addressed here for PHP core to solve as it is too time-consuming to be resolved on load. It either needs to be handled by: 1.) A tool like Composer, which already throws an error when such conflicting requirements occur, 2.) A tool like WordPress' plugin manager, which will just throw an error in a sandbox and let the user or site administrator resolve the issue, or 3.) PHP itself which would just throw an error when such a conflict emerges and lets the developer figure it out. Feels like you are just nerd-sniping here. > 3. Investigate the performance impact of maintaining multiple versions of the > same code in memory at once, when the order they get loaded will vary by > request. More nerd-sniping. By the same token I could say to you "Investigate the performance impact of maintaining a large number of autoloaders in the same codebase" — which I illustrated is happening — except you have the status-quo on your side. Performance impact due to "maintaining multiple versions of the same code in memory at once" is no different than the performance impact of maintaining multiple versions of equivalent code in memory at once that have had their namespaces rewritten. That is what those who have been forced to solve the same-symbol problem have been doing in userland. Most others have just given up on running two plugins when their dependencies conflict. It is not up to PHP to address when people load too much code into memory other than for PHP to fail to continue running. Yes, if people duplicate *exact* same code that should be addressed — ideally by Composer or the app itself — but if different versions cause performance problems its the site builder's responsibility to address, not PHP. > 4. Think through how you'd support *both* composer-based and "user managed" > applications with such a model, especially projects that are already > architecturally a decade out of date (like Wordpress). Already done. I explained how an `spl_autoload_map()` would do exactly that above. > When you have a proven that it's even possible to have multiple local symbol > tables, we can talk. Until then, please spare us. My one useful takeaway from your email — except that I already knew that — was the need to figure out how PHP can handle multiple symbol tables. Beyond that, your take your own advice and spare us (me) from your contempt and condescension as they are not good looks on anyone. -Mike [1] https://mikeschinkel.com/2014/the-decline-of-drupal-or-how-to-fix-drupal-8/ [2] https://w3techs.com/technologies/history_overview/content_management/ms/y [3] https://www.drupal.org/project/ludwig