Re: Versioned Packagers (Iteration IV)

From: Date: Tue, 09 Jul 2024 03:24:59 +0000
Subject: Re: Versioned Packagers (Iteration IV)
References: 1 2 3 4 5 6 7 8 9 10 11  Groups: php.internals 
Request: Send a blank email to [email protected] to get a copy of this message
> On Jul 8, 2024, at 5:41 AM, Rowan Tommins [IMSoP] <[email protected]> wrote:
> I agree. I wrote most of the below a couple of days ago, but I don't think it posted
> correctly, so apologies if some people see it twice: 
> 
> Autoloading is just a way to load files later, by the engine telling you when a class is first
> needed. PHP does not, and should not, make any assumptions about how files are laid out on disk; an
> autoloader doesn't actually need to load any files at all, and if it does, it uses the same
> include or require statements which have been in PHP for decades.

I think maybe you are replying to an earlier iteration by Michael Morris and have not seen the more
recent iteration?  

There he explored adding an additional function to named spl_autoload_map() where the
difference from spl_autoload_register() is that while the latter uses procedural code
to determine what should be loaded the former would use a declarative map to determine what should
be loaded. Then Composer and/or other tools could/would generate that map for PHP.

With an spl_autoload_map() PHP would not need to make any assumptions about how files
are laid out on disk. Instead, PHP would use a schema of a yet-to-be-determined data representation
format to discover  declaratively where files needed to be laid out on disk.

> Likewise, installing packages and defining version schemes is a completely separate problem
> space that can probably be served by a few small tweaks to Composer once the language provides the
> underlying functionality.
> 
> The core of the problem you seem to want to solve is this: if you have two files foo_1.php and
> foo_2.php, which both define a class \Acme\Foo, how do you load both of them, so that you end up
> with two differently named classes? 

That is one (1) of the core problems, yes.

> In JS, that's easy, because functions and object constructors (and "classes")
> exist as objects you can pass around as variables, they don't need to know their own name. In
> PHP, everything is based on the idea that functions and classes are identified by name. You can
> rewrite the name in the class declaration, and in direct references to it, but what about code using
> ::class, or constructing a name and using "new $name", and so on? How will tools using
> static analysis or reflection handle the renaming - e.g. how does DI autowiring work if names are in
> some sense dynamic?

This is one of the unfortunate	aspects of PHP never makes types a first-class data type. But I
digress.

> You've also got to work out what to do with transitive dependencies - if I "import
> 'foo_1.php' as MyFoo", but Foo in turn has "import 'guzzle_2.php' as
> MyGuzzle", what namespace do all Guzzle's classes get rewritten into? What about
> dependencies that are specifically intended to bridge between packages, like PSR-7 RequestInterface?

Which is a direct result of the other problem you mentioned, i.e. IOW without attempting to address
the prior problem this would not be a problem. #fwiw

> My advice: start with the assumption that something has already installed all the files you
> need into an arbitrary directory structure, and something is going to generate a bunch of statements
> to load them.

And this sentence is why I chose to reply to your message.  That assumption itself blocks the needs
of user-managed apps.

(Did you happen to read my compare-and-contrast of user-managed vs. developer-managed apps from a
few days ago?)

I feel it is likely those who have never worked professionally in PHP on user-managed apps like
WordPress  — which I assume describes you accurately? — are probably just simply unaware of the
problems that your assumptions cause for user-managed apps. And yes, some developers have no empathy
for others who have different circumstances, but I honestly don't think you (Rowan) are in the
category. 

Developer-managed apps use a build tool to put all vendor code in a single hierarchical set of
namespaces and then load needed code from there. But that really does not work for user-managed apps
like WordPress or Drupal.  Or at least not as they exist today, and probably not even if they were
rearchitected for the start.

What works for user-managed apps is that each add-on (plugin in WordPress,
module in Drupal) is stored in its own self-contained directory containing its own
vendor code — where some of the vendor code could easily be duplicated in another add-on — and
then the user-managed apps itself manages loading of all add-ons itself without a PSR-4 autoloader.
As it exists, there are no standard for how add-on filenames and directory structures much be named
nor how they are to load their dependencies so it is impossible for WordPress or Drupal to take on
that role using PSR-4 for them. 

Michael Morris' idea to add an spl_autoload_map() function would allow addressing
the needs of user-managed apps that treat each add-on as a self-contained entity. But making the
assumption that "something has already installed all the files you need into an arbitrary
directory structure" is not sufficient for the problems Michael Morris and I have been trying
to address.

An autoloader map schema that has enough information for PHP to understand how to manage the
conflicting names, and for the user-managed apps and Composer to be able to tell PHP what names are
conflicting is in fact a solid way forward.

-Mike


Thread (128 messages)

« previous php.internals (#124302) next »