Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-11 Thread Mike Schinkel


> On Jul 11, 2024, at 10:32 AM, Rowan Tommins [IMSoP]  
> wrote:
> 
> On Thu, 11 Jul 2024, at 12:26, Mike Schinkel wrote:
>> Let me use an analogy.  Envision two people on a city council of a small 
>> town.  One proposes the city should
>> implement a water, power and sewer grid so anyone who wants to build a new 
>> home or business in the city 
>> would be able to do so easily. 
> 
> This is a terrible analogy, IMHO. Here's a more pertinent one:

Sure, we can go back and forth and discredit each others analogies, but that's 
not going to change your mind nor likely mine.  

The crux of our disagreement is I see value on infrastructure services and you 
evidently do not.

> If you want to solve autoloading in WordPress, this is the wrong forum. 
> 
> Firstly, anything you do in core will not be adopted by WordPress, because it 
> will be 5+ years before their minimum PHP version is high enough to use it. 
> You're going to have to write a userland polyfill anyway.

That is what you are missing on this point. 

If PHP supported a cascading class map autoloader then a developer could build 
their sites and their plugins for that version of PHP without having to depend 
on WordPress changing to support it. And if they are distributing plugins they 
could build fallback mechanisms for earlier versions of PHP plus also recommend 
to their users that they upgrade to the newer versions of PHP. 

It is about empowering individuals developers, not about empowering WordPress. 

But, like I said, since anyone could no it, evidently no one will.

> Secondly, mapping namespaces to directories isn't the hard part for 
> WordPress. The hard part is integrating into their existing plugin installer 
> system - which already has a system for metadata, it doesn't need a new 
> config file - and persuading plugin authors to actually use it.

No, integrating into the plugin system would actually be quite easy per the 
class map design we've been discussing. I know the internals of that system 
well, I've probably debugged through it literally hundreds of times.

And sorry, the existing metadata system in WordPress has no information about 
plugin dependencies and is inadequate for that purpose. It only has an ini-like 
plugin header with basic information and is not suitable for dependencies. 
Also, "persuading plugin authors to actually use it" won't change a thing 
because they are already using it effectively, generally speaking.

> Maybe you also need Composer to make some changes to control it without the 
> CLI, so plugins can list their requirements and have them installed centrally.

That well could be.

> That's also not a subject for this list.

And we disagree, yet again.

Anyway, I am trying to avoid this thread so I can instead invest time in 
research and proof-of-concept work. Please don't pull me back in.

-Mike

Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-11 Thread Rowan Tommins [IMSoP]
On Thu, 11 Jul 2024, at 12:26, Mike Schinkel wrote:
> Let me use an analogy.  Envision two people on a city council of a small 
> town.  One proposes the city should
> implement a water, power and sewer grid so anyone who wants to build a new 
> home or business in the city 
> would be able to do so easily. 

This is a terrible analogy, IMHO. Here's a more pertinent one:

You have a city, where there is a working electricity grid. [That's 
autoloading, provided by PHP for many years.]

Most of the city are using a particular plug and socket system; the sockets 
aren't fitted by the electricity company, but the shops are full of devices 
that use these plugs, and most people have found the sockets really easy to 
fit. [That's Composer]

One district runs most of its appliances on gas, and has its own way of 
connecting them. People want to run electric appliances, and the grid goes 
right through the district, but for some reason, nobody's connected it up to 
the houses. So everyone has multiple gas-to-electricity converters, which is 
annoying. [That's WordPress]

Someone comes along, and rather than approaching the district [WordPress] and 
offering to help wire them to the existing grid, decides that what's needed is 
for the city to provide them with a new type of plug [a different autoloader 
function], which they won't be able to use immediately anyway.


> https://en.wikipedia.org/wiki/Interoperability
> https://en.wikipedia.org/wiki/Network_effect 

Adding something to core in the hope of it becoming a standard is exactly the 
opposite of the network effect. The network effect is "everyone already uses 
Composer, so nobody cares what PHP core does".

See also https://xkcd.com/927/ and since I used an electric plug analogy, check 
out the "international standard" plug, which has been adopted in exactly one 
country: https://en.wikipedia.org/wiki/IEC_60906-1


If you want to solve autoloading in WordPress, this is the wrong forum. 

Firstly, anything you do in core will not be adopted by WordPress, because it 
will be 5+ years before their minimum PHP version is high enough to use it. 
You're going to have to write a userland polyfill anyway.

Secondly, mapping namespaces to directories isn't the hard part for WordPress. 
The hard part is integrating into their existing plugin installer system - 
which already has a system for metadata, it doesn't need a new config file - 
and persuading plugin authors to actually use it.

Maybe you also need Composer to make some changes to control it without the 
CLI, so plugins can list their requirements and have them installed centrally. 
That's also not a subject for this list.

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-11 Thread Mike Schinkel
Preface:  I am going to bow out of this conversation now (unless pulled back 
in) and come back after 8.4 settles.

In the mean time I'll be working on two proof-of-concepts.  One is a totally 
userland PoC for packages being able to load same-named symbols, and the other 
will be working out how to use multiple symbol tables in PHP core. And as I 
have never modified php-src before, that is going to take some learning.

However, below are responses to Rowan and Larry.


> On Jul 10, 2024, at 8:33 AM, Rowan Tommins [IMSoP]  
> wrote:
> 
> On Wed, 10 Jul 2024, at 07:38, Mike Schinkel wrote:
>> 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.
> 
> Everything you've just described is possible, today, with no changes to PHP 
> core.

I described a **standardized format** that would be processed by PHP,

How exactly can any one individual implement a standardized format on their 
own, today?  One that anyone can depend on to be recognized and processed by 
any version of PHP after the one that first implemented it?

Rhetorical question. Of course.

> So let's step back a second, and look at the pros and cons of implementing it 
> in core:
> 
> Pros:
> - Possibly a bit faster if the C code can be optimised
> - "Blessed" by the PHP project, which makes it a standard of sorts

Or — without the blessing of a standard — as we sometimes say in the USA: 
"Besides that Mrs Lincoln, how was the play?"

Let me use an analogy.  Envision two people on a city council of a small town.  
One proposes the city should implement a water, power and sewer grid so anyone 
who wants to build a new home or business in the city would be able to do so 
easily. 

The other argues that anyone wanting to build can set up their own generator, 
dig their own well, and dig their own septic tank so why should the city 
provide such a grid? After all, anyone who is motivated enough can build 
"today," right?

Clearly that latter argument ignores the value of a central authority providing 
infrastructure others can just depend on existing, minimizing their cost, 
effort and risk. It also ignores that without that infrastructure most simply 
won't build there.

In PHP some bits like nice-to-have functions are easy enough to relegate to 
userland — although str_starts_with() and str_ends_with() sure are nice to just 
have like a community center in that city which all residents can use. OTOH, 
for infrastructure services, PHP benefits itself and others by providing them 
even if someone could build the functionality themselves.  

To be clear, the fact something is an infrastructure service itself is not 
sufficient to argue it *must* be included in PHP core — the need for service 
itself should stand on its own. 

However, it is enough (IMO) to show "you can do it yourself today" is not a 
valid argument against an infrastructure service. 

So can we please instead focus on the pros and cons of having such an 
infrastructure service instead of using the canard "you can build it yourself" 
as an argument against roads, power, and sewers?

If yes, we should discuss your list of pros and cons. 

HOWEVER, I think it is probably best to postpone any additional discussion 
until after 8.4 is released and any initial bugs are worked out so anyone 
interested could focus on the reasoning.

> On Jul 10, 2024, at 10:07 AM, Larry Garfield  wrote:
> 
> On Wed, Jul 10, 2024, at 1:38 AM, Mike Schinkel wrote:
> 
>>> 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.
> 
>> 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.
> 
> I find it amusing that several of your responses to me saying "you could do 
> this stupid thing but no one does 

Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-11 Thread Jordi Boggiano


On 2024-07-10 20:08, Michael Morris wrote:
On Wed, Jul 10, 2024 at 5:51 AM Jordi Boggiano  
wrote:



As for the rest of the thread, I feel like everyone needs to take
a few days to chill because it's getting a bit heated around here.

People are passionate about the things they love.  I've been busy with 
work and on Iteration V.  Details later this week, likely in the form 
of a github repo hosted markdown file that will be easier to follow, 
as the number of points to address is getting too lengthy to deal with 
in a list conversation and, more worryingly, people are glomming onto 
and criticizing the proposal for things already dropped.


Maybe if people are criticizing outdated versions of the spec it's 
because the first email came up exactly two weeks ago, and you're now on 
a 5th rewrite, and it all got mangled in the same 130+ email thread 
here. So yeah maybe someone missed some update..


That's why I said above, maybe take a breather, start a new thread with 
v5 in a week or two to get a fresh start.


Best,
Jordi

--
Jordi Boggiano
@seldaek -https://seld.be


Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-10 Thread Jordan LeDoux
On Wed, Jul 10, 2024 at 1:08 PM Michael Morris  wrote:

>
>
> I'm in no rush - though it might not seem that way. I don't see this being
> able to land before PHP 10. I'm pessimistic about the scope of these
> changes. It can be done - and pieces have often been discussed before, but
> they peter out. If they are to be solved some amount of stupid bulldog
> tenacity will be needed. I think I'm stupid enough to provide that, but I
> need to do it without being annoying.
>
> In any event these threads have already shown me a great deal of what I
> need to learn in order to get to an effective final form, whatever that is.
>

The point of people asking multiple times to wait until any other time of
year is not because anyone is worried you are trying to get it in right
away, it's because doing this kind of freeform "I don't know what I don't
know" discussion is unkind to all of the experts on the list who CAN tell
you "well, what you don't know is X". Most of them probably won't even
respond at this time of year, even if they did read, which they probably
didn't.

>
>
>>
>> >1. Import Maps - These would be prepared by hand or by a package manager
>> >like composer.
>>
>> As Larry mentioned, there was a proposal for this a while ago, but not
>> much enthusiasm, since it's so easy to implement in userland, and doing so
>> means we don't have to include all the possible options someone might want.
>>
>>
>> > it will be able to detect symbols the autoload
>> >system cannot: functions and constants.
>>
>> Autoloading functions and constants isn't blocked by autoloaders being
>> procedural, it's blocked by the unfortunate decision made many years ago
>> that a function call like "strlen" dynamically falls back to meaning
>> "\strlen", rather than being resolved once at compile-time like class
>> names.
>
>
>> So far, nobody's quite cracked how that should interact with autoloading.
>> Don't expect this to be easy.
>>
>
> At worst this is the sort of "unfortunate decision" that can be eschewed
> in the PHP module files to make them easier to work with.  But I really do
> need a list of these things we'd love to do but can't because of reasons.
>
>

That's your job as the proposer. :)


>
>> >2. Packages - Packages load differently and can effectively monkey-type
>> the
>> >code of an existing package on the fly in much the same way that
>> namespaces
>> >themselves work with symbol names as a flat string replace.
>>
>> This is an interesting - but extremely complex - problem, and the one
>> I've been urging you to focus on if you're really up for the challenge. It
>> probably needs quite a deep dive into how the language works to find out
>> what assumptions it's going to break. (If you're just going to talk about
>> configuration, and not the actual implementation, don't expect much
>> enthusiasm.)
>>
>
> I need to know where to start, beyond cloning the PHP source code repo -
> which I have.  Any advice on where to look would be appreciated.
>

Try to change something, compile, then debug a test file with it. That's
how I went from "has only done basic C" to "wrote almost all of the
implementation of operator overloads" in a few months. Once you start on
that, you'll be able to ask more specific questions that are more likely to
get a specific and quick response. You'll want to know "when do we use this
macro" and so on.

You can also reference all the documentation that has been built for people
who are getting into learning the PHP source:

https://www.phpinternalsbook.com/index.html


>
>> > Existing code
>> >can be loaded into packages, but also an outline for writing packages
>> that
>> >have privacy modifiers to their members - i.e. protected class SomeClass
>> {}
>>
>> This part seems interesting, as long as it's not tied heavily into other
>> changes; existing code using /** @internal */ should ideally need minimal
>> changes to make use of it.
>>
>>
>>
>> >3. Modules - Files which are code first instead of template first.
>>
>> If by "template first" you mean "you have to write > repeat my earlier "meh". I'm pretty sure it's also been discussed before,
>> and dropped when it met with that general reaction.
>>
>> The name "modules" implies something more, so maybe I should reserve
>> judgement. Having both "packages" and "modules" sounds pretty confusing
>> though.
>>
>
> The largest thrust of modules is to step forward with changes that are
> desirable but impossible to implement because of BC breaks brought on by
> unfortunate design decisions like the one mentioned previously.  Likely
> these will be visited on a case by case basis.  For another is the need of
> classes to have the function keyword all over the place.
>
> It could end up that things like package privacy can only be supported in
> the modules.  As to the difference, since it meanders all of the place
> here's the defs I'm going with - A module is a file.  A package is a
> collection of files.
>

So then the purpose of modules, to you, 

Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-10 Thread Rowan Tommins [IMSoP]



On 10 July 2024 21:04:41 BST, Michael Morris  wrote:
>The largest thrust of modules is to step forward with changes that are
>desirable but impossible to implement because of BC breaks brought on by
>unfortunate design decisions like the one mentioned previously.  Likely
>these will be visited on a case by case basis.  For another is the need of
>classes to have the function keyword all over the place.

That sounds like a one-time chance for some fairly random changes you happen to 
like the idea of, at the cost of permanently forking the language into two 
dialects. It doesn't sound much to do with "modules", and I don't think it will 
be popular.


>It could end up that things like package privacy can only be supported in
>the modules. 

Please, please, don't do that. I don't want to rewrite a bunch of code into a 
different flavour of the language, just to make use of a new feature that has 
nothing to do with those changes.

Rowan Tommins
[IMSoP]


Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-10 Thread Michael Morris
On Wed, Jul 10, 2024 at 3:29 PM Rowan Tommins [IMSoP] 
wrote:

>
>
> On 10 July 2024 19:08:39 BST, Michael Morris  wrote:
>
> Just to repeat a point that's been raised a few times: this is not a great
> time of year for this kind of discussion. If you come back after 8.4 is
> baked, you may get more enthusiasm. That will also give you time to make
> some more detailed analysis, so we don't have to argue about hypothetical
> difficulties.
>

I'm in no rush - though it might not seem that way. I don't see this being
able to land before PHP 10. I'm pessimistic about the scope of these
changes. It can be done - and pieces have often been discussed before, but
they peter out. If they are to be solved some amount of stupid bulldog
tenacity will be needed. I think I'm stupid enough to provide that, but I
need to do it without being annoying.

In any event these threads have already shown me a great deal of what I
need to learn in order to get to an effective final form, whatever that is.


>
> >1. Import Maps - These would be prepared by hand or by a package manager
> >like composer.
>
> As Larry mentioned, there was a proposal for this a while ago, but not
> much enthusiasm, since it's so easy to implement in userland, and doing so
> means we don't have to include all the possible options someone might want.
>
>
> > it will be able to detect symbols the autoload
> >system cannot: functions and constants.
>
> Autoloading functions and constants isn't blocked by autoloaders being
> procedural, it's blocked by the unfortunate decision made many years ago
> that a function call like "strlen" dynamically falls back to meaning
> "\strlen", rather than being resolved once at compile-time like class
> names.


> So far, nobody's quite cracked how that should interact with autoloading.
> Don't expect this to be easy.
>

At worst this is the sort of "unfortunate decision" that can be eschewed in
the PHP module files to make them easier to work with.  But I really do
need a list of these things we'd love to do but can't because of reasons.


>
> >2. Packages - Packages load differently and can effectively monkey-type
> the
> >code of an existing package on the fly in much the same way that
> namespaces
> >themselves work with symbol names as a flat string replace.
>
> This is an interesting - but extremely complex - problem, and the one I've
> been urging you to focus on if you're really up for the challenge. It
> probably needs quite a deep dive into how the language works to find out
> what assumptions it's going to break. (If you're just going to talk about
> configuration, and not the actual implementation, don't expect much
> enthusiasm.)
>

I need to know where to start, beyond cloning the PHP source code repo -
which I have.  Any advice on where to look would be appreciated.


>
>
> > Existing code
> >can be loaded into packages, but also an outline for writing packages that
> >have privacy modifiers to their members - i.e. protected class SomeClass
> {}
>
> This part seems interesting, as long as it's not tied heavily into other
> changes; existing code using /** @internal */ should ideally need minimal
> changes to make use of it.
>
>
>
> >3. Modules - Files which are code first instead of template first.
>
> If by "template first" you mean "you have to write  repeat my earlier "meh". I'm pretty sure it's also been discussed before,
> and dropped when it met with that general reaction.
>
> The name "modules" implies something more, so maybe I should reserve
> judgement. Having both "packages" and "modules" sounds pretty confusing
> though.
>

The largest thrust of modules is to step forward with changes that are
desirable but impossible to implement because of BC breaks brought on by
unfortunate design decisions like the one mentioned previously.  Likely
these will be visited on a case by case basis.  For another is the need of
classes to have the function keyword all over the place.

It could end up that things like package privacy can only be supported in
the modules.  As to the difference, since it meanders all of the place
here's the defs I'm going with - A module is a file.  A package is a
collection of files.


Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-10 Thread Rowan Tommins [IMSoP]



On 10 July 2024 19:08:39 BST, Michael Morris  wrote:

Just to repeat a point that's been raised a few times: this is not a great time 
of year for this kind of discussion. If you come back after 8.4 is baked, you 
may get more enthusiasm. That will also give you time to make some more 
detailed analysis, so we don't have to argue about hypothetical difficulties.


>1. Import Maps - These would be prepared by hand or by a package manager
>like composer.

As Larry mentioned, there was a proposal for this a while ago, but not much 
enthusiasm, since it's so easy to implement in userland, and doing so means we 
don't have to include all the possible options someone might want.


> it will be able to detect symbols the autoload
>system cannot: functions and constants.

Autoloading functions and constants isn't blocked by autoloaders being 
procedural, it's blocked by the unfortunate decision made many years ago that a 
function call like "strlen" dynamically falls back to meaning "\strlen", rather 
than being resolved once at compile-time like class names.

So far, nobody's quite cracked how that should interact with autoloading. Don't 
expect this to be easy.


>2. Packages - Packages load differently and can effectively monkey-type the
>code of an existing package on the fly in much the same way that namespaces
>themselves work with symbol names as a flat string replace.

This is an interesting - but extremely complex - problem, and the one I've been 
urging you to focus on if you're really up for the challenge. It probably needs 
quite a deep dive into how the language works to find out what assumptions it's 
going to break. (If you're just going to talk about configuration, and not the 
actual implementation, don't expect much enthusiasm.)


> Existing code
>can be loaded into packages, but also an outline for writing packages that
>have privacy modifiers to their members - i.e. protected class SomeClass {}

This part seems interesting, as long as it's not tied heavily into other 
changes; existing code using /** @internal */ should ideally need minimal 
changes to make use of it.



>3. Modules - Files which are code first instead of template first.

If by "template first" you mean "you have to write 

Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-10 Thread Michael Morris
On Wed, Jul 10, 2024 at 5:51 AM Jordi Boggiano  wrote:

>
> As for the rest of the thread, I feel like everyone needs to take a few
> days to chill because it's getting a bit heated around here.
>
People are passionate about the things they love.  I've been busy with work
and on Iteration V.  Details later this week, likely in the form of a
github repo hosted markdown file that will be easier to follow, as the
number of points to address is getting too lengthy to deal with in a list
conversation and, more worryingly, people are glomming onto and criticizing
the proposal for things already dropped.

In particular - I'm not talking about ditching composer.  I don't want to
get in the business of building a package manager, especially when there's
an existing one.

Some highlights of what I am working on

1. Import Maps - These would be prepared by hand or by a package manager
like composer. An internal autoloader will work with them. Unlike autoload
functions, import maps get merged together so the actual seek operation can
remain optimized.  Given Composer already can build an optimized class map
file it is already well positioned to feed information into this code. The
reason to use it is that it will be able to detect symbols the autoload
system cannot: functions and constants. It will also be able to load
packages and modules.
2. Packages - Packages load differently and can effectively monkey-type the
code of an existing package on the fly in much the same way that namespaces
themselves work with symbol names as a flat string replace. Existing code
can be loaded into packages, but also an outline for writing packages that
have privacy modifiers to their members - i.e. protected class SomeClass {}
3. Modules - Files which are code first instead of template first.

These are being prepped as at least 3 interrelated RFC drafts which can be
dealt with piecemeal, and any of the three not receiving enough support for
inclusion doesn't preclude the others from going forward.


Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-10 Thread Larry Garfield
On Wed, Jul 10, 2024, at 1:38 AM, Mike Schinkel wrote:

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


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

I find it amusing that several of your responses to me saying "you could do 
this stupid thing but no one does that" is "WordPress does that thing."  I make 
no comment other than to observe it.

But let me understand: In a thread started by Michael Morris where he 
explicitly said the most important thing for him is multi-version loading, 
you're going to insist you're talking only about moving Composer's classmap 
logic into core, and nothing about multi-version loading.

If that's the case, then please be polite to Michael Morris and get out of his 
thread.

Also, be aware that classmap-in-core was already discussed 3 years ago and went 
nowhere.

https://wiki.php.net/rfc/autoload_classmap
https://externals.io/message/113545

Largely because, as Sara said then, and Rowan just said on this thread, it can 
be done better in user-space and is already done better in user-space... by 
Composer.

https://externals.io/message/113569

You even commented in that thread:

https://externals.io/message/113554

So it's not a new idea, it's an idea that's already been greeted with a general 
"meh".

Yes, most "developer managed apps" use Composer today to side-step the 
"bajillion autoloaders" problem.  It's a solved problem.

Nothing precludes Wordpress from doing the same.  I admittedly have not looked 
at WP's core in a very long time, but I would be absolutely shocked if it 
wasn't pretty straightforward to build code into WP core that looks at the 
source directories of all plugins, finds the classes there, and builds a big 
index (stored in a cache directory or the database) that it can use in one 
single autoloader registered by WP itself.  I know that can be done, because 
that's exactly how Drupal 7's autoloader worked.  I know, because I wrote it.  
In 2008.  (It was later modified by others, but the initial version was mine.)

That would work even with WP's "download code and drop it on disk" model.  That 
has been possible since PHP 5.2 at least, when I wrote exactly that for Drupal. 
 It wasn't even that hard.  Literally any "user managed app" could do the same.

Why hasn't WP core done that in order to make life easier for plugin developers 
and avoid registering 50 separate autoloaders?  I dunno, you should ask Matt 
Mullenweg.  We have nothing to do with it.

--Larry Garfield


Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-10 Thread Rowan Tommins [IMSoP]
On Wed, 10 Jul 2024, at 07:38, Mike Schinkel wrote:
> 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.

Everything you've just described is possible, today, with no changes to PHP 
core. And the easiest way to implement it is to borrow the existing 
battle-tested implementation in Composer, maybe tweaking it with plugins, and 
automating it with its PHP API rather than using its CLI interface.

If you look at "vendor/composer/autoload_psr4.php" in a project where you've 
run "composer install", you'll find a mapping of namespaces to directories; 
PSR-4 then defines where individual classes are within each of those 
directories. If you tell Composer to dump an optimized autoloader, it will 
instead create a mapping of individual class names to file paths.

So let's step back a second, and look at the pros and cons of implementing it 
in core:

Pros:
- Possibly a bit faster if the C code can be optimised
- "Blessed" by the PHP project, which makes it a standard of sorts
- No library code to copy or install into a project

Cons:
- Requires a minimum PHP version to run (a huge problem for WordPress, famous 
for its broad version support)
- Improvements can only be accessed by updating PHP
- Breaking changes are nearly impossible, because users can't choose between 
major versions within one version of PHP
- Limited ability to tweak for a particular project if the standard solution 
doesn't meet their needs

Things that won't change:
- You still need a standard layout of files within each directory (e.g. PSR-4, 
or whatever layout you prefer), or to run something that analyzes your code and 
generates a comprehensive class map (i.e. does the same job as Composer's 
optimized autoload generator)
- The application still needs some central code to register those directory or 
file lists, e.g. when you install a WordPress plugin, something has to load its 
configuration file
- PHP still won't be able to have two classes with the same name, because 
that's a completely separate problem, unrelated to autoloading

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-10 Thread Mike Schinkel
> On Jul 10, 2024, at 5:50 AM, Jordi Boggiano  wrote:
> 
> On 2024-07-09 05:24, Mike Schinkel wrote:
>> 
>>  
>> 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. 
>> 
> Just one note here: You keep saying user-managed apps but from what I can 
> tell, these problems really only apply to WordPress.

There are numerous others, such as Joomla, Phalcon, CMS Made Simple, 
TextPattern, OpenCart, ExpressionEngine and ProcessWire. 

But yes, the fact that WordPress has well over 50% marketshare of CMS and 
dwarfs all the others by well over an order of magnitude makes it appear that 
it only really applies to WordPress.

Which, given the number of users for each, it kinda does. But that also begs 
the question if dismissing the PHP app with by-far the largest user base is the 
smartest approach?

> There are others like Contao CMS who decided as a project they wanted 
> user-managed plugins but also wanted to rely on Composer and its ecosystem of 
> packages, and they made it happen [1]

I just scoured the Contao website and the websites of a few of their 3rd party 
extensions and after quite a bit of detective work I found how Contao allows 
user-managed plugins, per se.  They did not make it obvious on their site how 
to do it, though.

First you have to download and install a `.phar file called Contao Manager[1] 
and install it on your server. Which yeah, a developer could do for an 
end-user, but most end-users are going to be blocked by this. 

Second, to use Contao Manager you have to have a PHP installation that allows 
using the functions proc_open()/proc_close() and allow_url_fopen() which AFAIK 
most responsible web hosts lock down on a shared server, which is the majority 
of WP hosting. The reason those are required is Contao Manager is just using 
Composer on the backend via CLI to install and manage plugins. 

So while yes, Contao does allow users to manage plugins, that was not what I 
meant when I made a distinction between user-managed and developer-managed 
apps. To me, Contao is squarely in the developer-managed app category.

> So while I have some sympathy for all developers stuck maintaining WP sites, 
> and plugin authors not willing to do everything themselves and deciding to 
> bundle a vendor dir with Composer-installed dependencies.. It feels like 
> you're all kinda held hostage with the choices of the WordPress project, 
> which sucks for sure but saying it is unfixable is not helping.

How are you envisioning it be fixed?   

If there are ways to fix things that do not require WordPress to make a change 
with major BC breakage nor require users upgrade web hosts to support dedicated 
features I would be very happy to find out what those are.

And yes, to concur by also clarify, developers are held hostage by the 
*combined* choices of the WordPress and the PHP projects. It is kinda like 
being a kid with needs but also with feuding parents. ¯\_(ツ)_/¯

-Mike

[1] https://docs.contao.org/manual/en/installation/contao-manager/


Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-10 Thread Jordi Boggiano

On 2024-07-09 05:24, Mike Schinkel wrote:

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.


Just one note here: You keep saying user-managed apps but from what I 
can tell, these problems really only apply to WordPress.


There are others like Contao CMS who decided as a project they wanted 
user-managed plugins but also wanted to rely on Composer and its 
ecosystem of packages, and they made it happen [1].


So while I have some sympathy for all developers stuck maintaining WP 
sites, and plugin authors not willing to do everything themselves and 
deciding to bundle a vendor dir with Composer-installed dependencies.. 
It feels like you're all kinda held hostage with the choices of the 
WordPress project, which sucks for sure but saying it is unfixable is 
not helping.


As for the rest of the thread, I feel like everyone needs to take a few 
days to chill because it's getting a bit heated around here.


Best,
Jordi

[1] https://docs.contao.org/manual/en/installation/contao-manager/

--
Jordi Boggiano
@seldaek -https://seld.be


Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-10 Thread Mike Schinkel
> On Jul 10, 2024, at 2:56 AM, Jordan LeDoux  wrote:
> 
> On Tue, Jul 9, 2024 at 11:42 PM Mike Schinkel  > wrote:
> [snip]
> 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.
> 
> While Larry was very blunt (and I don't really fault him for that either), 
> that should not be your only takeaway. The short version was that he was 
> telling you, and the other people in this thread, to stop pontificating and 
> to do something that resembles developing/researching a solution.

Why support a claim that assumes I have not been developing/researching a 
solution when you have absolutely no knowledge of what I have been doing? (I 
have in-fact been researching and developing a PoC. Full time for the past 
week, actually.)

> A lot of the people who actually have experience working on the engine are 
> literally ignoring this conversation right now (and may come back to it next 
> month) because it's just too much noise and nonsense right when we're near 
> feature freeze.
> 
> Your focus and intent to drive this discussion towards trying to duplicate 
> composer reduces its usefulness. I get that you do not like 
> PSR-4/composer/whatever. I honestly cannot wade through the 15,000-ish words 
> you've sent in these threads to nail down the specifics. But I know for a 
> fact that an attempt to redesign composer is:

You claim "my focus and intent" is to "duplicate composer" and yet you claim 
you "honestly cannot wade through the 15,000-ish words?"  

If you haven't read my email, then how exactly do you know what my focus and 
intent has been?

In fact, my focus and intent has *not* been to duplicate composer. FULL STOP.

But since I already fully explained my focus and intent then — other than the 
fact you didn't read it — it would do a disservice to everyone to repeat it.

> 1. Orthogonal to PHP modules (they have nothing to do with each other from a 
> design perspective).
> 2. Doomed to failure. 
> 
> Your one useful takeaway, that Larry gave you specific steps for, is to focus 
> on the feature the original proposer of the thread was trying for, instead of 
> continuing to derail it into composer-related nonsense.

If you wanted to quiet a thread that obviously annoys you for some reason it 
would seem the last thing you to do is immediately knee-jerk a reply with three 
(3) different straw man accusations — each of which can easily be disproven by 
reading my email to which you replied — when just ignoring the email was your 
option.

-Mike

Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-10 Thread Jordan LeDoux
On Tue, Jul 9, 2024 at 11:42 PM Mike Schinkel  wrote:

> [snip]
> 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.
>
>
While Larry was very blunt (and I don't really fault him for that either),
that should not be your only takeaway. The short version was that he was
telling you, and the other people in this thread, to stop pontificating and
to do something that resembles developing/researching a solution. A lot of
the people who actually have experience working on the engine are literally
ignoring this conversation right now (and may come back to it next month)
because it's just too much noise and nonsense right when we're near feature
freeze.

Your focus and intent to drive this discussion towards trying to duplicate
composer reduces its usefulness. I get that you do not like
PSR-4/composer/whatever. I honestly cannot wade through the 15,000-ish
words you've sent in these threads to nail down the specifics. But I know
for a fact that an attempt to redesign composer is:

1. Orthogonal to PHP modules (they have nothing to do with each other from
a design perspective).
2. Doomed to failure.

Your one useful takeaway, that Larry gave you specific steps for, is to
focus on the feature the original proposer of the thread was trying for,
instead of continuing to derail it into composer-related nonsense.

Jordan


Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-10 Thread Mike Schinkel
> On Jul 9, 2024, at 1:15 PM, Larry Garfield  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.
>> 
>> 
> 
> 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 

Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-09 Thread Rob Landers
On Tue, Jul 9, 2024, at 19:15, Larry Garfield wrote:
> On Sat, Jul 6, 2024, at 1:12 AM, Mike Schinkel wrote:
> 
> > 
> >
> > Reading this however caused me to ponder things certain people has said 
> > recently — and many people have said for years on this list — and I 
> > think I am recognizing something that I have always known but never put 
> > the pieces together before.
> >
> > Many (most?) people on PHP Internals view WordPress coding standards as 
> > bad and some even view addressing WordPress developers needs as bad for 
> > PHP. And in general I concur that those people are reasonably justified 
> > in their belief WordPress' coding standards are not the standards that 
> > PHP developer who want to do professional level software engineering 
> > should aspire. 
> >
> > And since many (most?)* *PHP Internals members generally do not 
> > experience the issues that WordPress developers have they do not 
> > recognize that they are issues; IOW, *"out of sight, out of mind." *
> >
> > I also think some list members tend to dismiss WordPress developers 
> > pains as unimportant and/or think that addressing those pains have will 
> > harm* *PHP. 
> >
> > (BTW, I recently had a dialog off-list with someone who wrote in an 
> > email that *"Wordpress is an exception, but nobody these days treats 
> > WordPress as a valid example to do anything. It is an ancient piece of 
> > legacy code that has no bearing on modern situation and it's their 
> > problem to deal with." *So I am not just erecting a straw man here.)
> >
> > But I think what most may not consciously recognize is that* WordPress 
> > is a different type of web app* than an app build using Symfony or 
> > Laravel and deployed by its developers, or by some other professional 
> > developer. 
> >
> > 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.
> >
> > 
> 
> 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.
> 
> 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.  
> 
> 

Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-09 Thread Larry Garfield
On Sat, Jul 6, 2024, at 1:12 AM, Mike Schinkel wrote:

> 
>
> Reading this however caused me to ponder things certain people has said 
> recently — and many people have said for years on this list — and I 
> think I am recognizing something that I have always known but never put 
> the pieces together before.
>
> Many (most?) people on PHP Internals view WordPress coding standards as 
> bad and some even view addressing WordPress developers needs as bad for 
> PHP. And in general I concur that those people are reasonably justified 
> in their belief WordPress' coding standards are not the standards that 
> PHP developer who want to do professional level software engineering 
> should aspire. 
>
> And since many (most?)* *PHP Internals members generally do not 
> experience the issues that WordPress developers have they do not 
> recognize that they are issues; IOW, *"out of sight, out of mind." *
>
> I also think some list members tend to dismiss WordPress developers 
> pains as unimportant and/or think that addressing those pains have will 
> harm* *PHP. 
>
> (BTW, I recently had a dialog off-list with someone who wrote in an 
> email that *"Wordpress is an exception, but nobody these days treats 
> WordPress as a valid example to do anything. It is an ancient piece of 
> legacy code that has no bearing on modern situation and it's their 
> problem to deal with." *So I am not just erecting a straw man here.)
>
> But I think what most may not consciously recognize is that* WordPress 
> is a different type of web app* than an app build using Symfony or 
> Laravel and deployed by its developers, or by some other professional 
> developer. 
>
> 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.
>
> 

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.

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.  We dismiss Wordpress generally because

1. WP actively harms the PHP community by encouraging the use of ancient PHP 
versions with known security issues.
2. WP's 

Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-09 Thread Rowan Tommins [IMSoP]



On 9 July 2024 04:24:59 BST, Mike Schinkel  wrote:
>I think maybe you are replying to an earlier iteration by Michael Morris and 
>have not seen the more recent iteration?  

I wrote the message a few days ago, but it didn't post; but the more recent 
discussion still seems to be focussing on things that can be solved in 
userland, rather than the fundamentally hard parts.


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

You can implement this in userland, right now. The point of calling procedural 
code for the autoloader is that it can do anything it likes to define the 
symbol - it can look it up in a table of directories, it can load some code 
from a database and eval() it, whatever you need. In fact, Composer already 
does implement such a file map, that's what its "optimize autoloader" option 
creates.

What you can't easily do is run different code depending on where the symbol is 
used - but since the autoloader is only called once per symbol, doing so 
wouldn't make much sense.



>> 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.
>
[...]
>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

Note that I said "arbitrary directory structure", not "PSR-4/Composer directory 
structure"; the files are on disk somewhere. PHP didn't put them there, some 
application did. The application knows where they are, and needs to tell PHP 
somehow.


> — where some of the vendor code could easily be duplicated in another add-on

This is the hard part I was suggesting you focus 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.

WordPress doesn't need PHP Internals, or even PHP-FIG, to define how plugins 
should be laid out on disk, and to write an autoloader for whatever they come 
up with.


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

It doesn't need to solve all the needs of the application, it needs to solve 
the parts we don't already have. WordPress already knows how to download files 
to disk; it could trivially design a system for plugin authors to lay out their 
own classes in some agreed layout and write an autoloader using the 
functionality that's been around since PHP 5.3.

The part it can't do is load two classes with the same fully-qualified name, 
because the language has no base functionality to build that on. Designing 
configuration files is a complete waste of time until you've designed that base 
functionality: when you load two classes with the same fully-qualified name, 
what exactly do you want the engine to do? What will need to change in the core 
of the language to make that possible?

Regards,
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-08 Thread Mike Schinkel
> On Jul 8, 2024, at 5:41 AM, Rowan Tommins [IMSoP]  
> 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 

Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-08 Thread Jordan LeDoux
On Mon, Jul 8, 2024 at 2:42 AM Rowan Tommins [IMSoP] 
wrote:

>
>
> On 8 July 2024 04:25:45 CEST, Jordan LeDoux 
> wrote:
> >I think it's strange that this discussion has driven deep down the tangent
> >of versioning...
> [...]
> >Things like separating global scope between importer and importee, managed
> >visibility of symbols and exports from modules/packages, allowing for
> >separate autoloaders for things which are called or included via an
> import,
> >etc. Those are the things that the language itself can do.
> >
> >All this other stuff feels like a distraction.
>
> 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.
>
> 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?
>
> 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?
>
> 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?
>
> 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. What happens next,
> in the language itself, to make them live side by side without breaking? If
> we get a solid solution to that (which I'm skeptical of), we can discuss
> how Composer, or the WordPress plugin installer, would generate whatever
> include/import/alias/rewrite statements we end up creating.
>
> Regards,
> --
> Rowan Tommins
> [IMSoP]
> Rowan Tommins
> [IMSoP]
>

I think it could be done somewhat simply (relative to the other things that
have been discussed) if the engine reserved a specific namespace for
imported symbols internally. Something like:

`\__Imported\MyImportStatement`

Where the `\__Imported` namespace is reserved and throws a parser error if
it occurs in code anywhere, and `MyImportStatement` corresponds to an
application importing the code using something like `import MyPackage as
MyImportStatement;`

Then, all symbols which are loaded into the global space as a result of the
import are actually rewritten into the hidden namespace the engine actually
uses under the hood, and any uses from the import statement in the
application code which has the import would reference the symbols in the
prefixed namespace.

This would not be trivial however. The engine code which supports this
would need to keep track of a kind of "context" for each file, based on
what namespace the file was included from. For instance, if an autoload
occurs inside the package that was loaded into `MyImportStatement`, the
engine would need to be aware that the code being executed is defined in
that namespace, REGARDLESS of whether it was a class, function, or
statement, and load ALL symbols that are created as a result into the
rewritten namespace. It would also need to translate in the other direction
for `use` statements inside the package, since it would not know ahead of
time what rewritten namespace it would actually be loaded in.

However, this is the simplest solution I see that doesn't involve writing a
second PHP engine just for this sort of thing.

Jordan

PS: For those unaware, for each "symbol" (something that has a unique
referenceable name in the code, roughly), there is at least one name that
refers to ONLY that thing internally. (I'm fairly certain that there are NO
situations where one name can refer to two things at all, but I am not

Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-08 Thread Rowan Tommins [IMSoP]



On 8 July 2024 04:25:45 CEST, Jordan LeDoux  wrote:
>I think it's strange that this discussion has driven deep down the tangent
>of versioning...
[...]
>Things like separating global scope between importer and importee, managed
>visibility of symbols and exports from modules/packages, allowing for
>separate autoloaders for things which are called or included via an import,
>etc. Those are the things that the language itself can do.
>
>All this other stuff feels like a distraction.

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.

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? 

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?

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?

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. What happens next, in the 
language itself, to make them live side by side without breaking? If we get a 
solid solution to that (which I'm skeptical of), we can discuss how Composer, 
or the WordPress plugin installer, would generate whatever 
include/import/alias/rewrite statements we end up creating.

Regards,
-- 
Rowan Tommins
[IMSoP]
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-07 Thread Jordan LeDoux
On Wed, Jul 3, 2024 at 5:18 PM Michael Morris  wrote:

> Hello all. Hitting reset again as the primary problem at hand has become
> clear.  Let's recap it.
>
> Autoloading is great for loading packages, but it can't load different
> versions of the same package at the same time.  Why would you want to do
> that?
>
> When you don't have full control of the code.
>
> For example, consider Drupal.  It is running Twig at some version of 3 at
> the moment. Suppose Twig 4 is introduced with significant backward
> compatibility breaks (Not saying the authors would do such a thing) but
> also wonderful features.
>
> If you're writing a Drupal extension you might want to use this new Twig.
> This is possible if you are willing to monkey-type the package - that is,
> have a code package traverse over the entire package and change all
> instances of `namespace Twig` in the files to `namespace NewTwig`. You can
> then use the package at the namespace of \NewTwig.
>
> This is painful, but the pain factor increases if multiple extension
> developers choose to do the same thing.  Each extension using its own Twig
> library is going to incur a performance hit.
>
> One upshot of this is I've noted that major package distributors, like
> Symfony, take BC into account with major releases - and may not develop new
> features or change things in those releases out of fear of people not
> wanting to upgrade.
>
> Now don't get me wrong, changing things just because is a bad thing. If a
> BC can be avoided it should be. But having a mechanism to move forward is
> important.
>
> In some ways versioning packages is like static typing variables. It
> doesn't seem important at all until you are faced with a problem only it
> can solve, or faced with a problem created by dynamic typing of variables.
>
> What can be done in the engine?
>
> Well first off, recognize that autoloading isn't going to work with a
> versioned package scheme. Autoloaders, regardless of their resolution
> schema be it PSR-0, PSR-4, or BobbysFirstAutoloader-Scheme can only have
> one symbol per package, set by the namespace.
>
> Can PHP support multiple packages without rewriting the whole engine?  I
> think so, but it isn't trivial, and the side effects need to be cordoned
> off so that those who need this complexity can have it while the beginning
> and intermediate coders can ignore it just like they ignore strict
> comparison operators and strict typing unless a library they are trying to
> use foists it on them.
>
> This is why I advocate a new keyword for this - import.  Import's behavior
> is most similar to require_once, but it doesn't have to be the same.  Since
> it is a new entrypoint into the engine the way the engine considers the
> code can be different - whether slightly different or radically different
> is a debate for another time. I'm going to stick with only those changes
> that make sense in the context of package links.
>
> Let's start with the simplest problem, importing this file.
>
>   namespace A;
>   function foo() { echo 'Hi'; }
>
> To review, if we require_once this file we'll find the function at
> \A\foo().  If our current file uses the same namespace we can just use foo()
>
> At its root import would do the same. `import "file.php"` would do the
> same as a require_once assuming there's no difference between the file
> structure rules for import - again there is opportunity here, but it's not
> a requirement.
>
> If that's all it does, it's pointless.  However, import can alias.
>
>   import 'file.php' as B;
>
> Now we have \B\foo();  This makes it relatively easy to have two different
> versions of the package running since in our own code we can always
> reference the foo in the B namespace. But while that allows limited package
> versioning, it doesn't solve the multiple extensions wanting to use the new
> stuff problem outlined above.
>
> So we have to call out the version in code, like so.
>
>   import 'file.php v1.0.0';
>
> A simple space separates the version from the file.  If the filename has a
> space, well \ characters aren't just for namespaces.
>
> Now for the first real behavior difference between import and
> require_once, even if we aren't doing anything fancy.  Import cares about
> the namespace it's invoked from.  Require_once does not.  To illustrate
> this behavior he's some pseudocode - we are including the file.php given
> earlier
>
>   namespace D;
>   require_once 'file.php';
>
>   \A\foo(); // Hi.
>
>   import 'file.php';
>
>   \D\A\foo(); // Hi.
>
> See that? The namespace of the calling file is prepended to the namespace
> contained in the import.
>
> Why?  What's the value here?  I'll explain.
>
> Now, let's suppose we do have two versions of file.php. So in addition to
> the above, elsewhere in the code this happens
>
>   namespace C;
>   import 'file.php v2.0.0'
>
>   A\foo(); // Welcome, since version 2 echoes welcome. Remember your
> namespace resolution rules - this import is actually at:
>   

Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-07 Thread Mike Schinkel
> On Jul 6, 2024, at 8:01 PM, Michael Morris  wrote:
> 
> Some context from where I'm coming from.  I have been working exclusively in 
> React, NodeJS and Go up till about a year ago, and in Drupal before that - it 
> being 10 years since the last time I looked at WordPress. I need work though, 
> and I was offered a job where about two-thirds of my workload is a massive 
> WordPress site that has grown well outside the scope WordPress does best.  So 
> I've been getting used to it again and added some ulcers along the way.

Yes, a university semester could be filled with the dynamics of open-source 
when a project's user base and those overseeing its governance diverge. #fwiw

BTW, you don't happen to be working for my last WordPress client, are you? 

> 
> ...
> Many (most?) people on PHP Internals view WordPress coding standards as bad 
> and some even view addressing WordPress developers needs as bad for PHP
> 
> I really don't want to get into that crossfire. WordPress is the 800lb. 
> gorilla of the PHP app world having more server market share that is dominant 
> - how dominant depends on who you ask. The most conservative estimate I've 
> seen is about half of PHP sites are running WordPress, and the most pro-WP 
> quote I saw claimed it has around 80% share.

The reality is it does not matter if you want to or not, by arguing for a 
feature on PHP Internals that is needed more by user-managed apps like 
WordPress than developer-managed apps, you have stepped into said crossfire.

You do not get to pick your reality, your reality picks you.

>>   B/ = './path/to/B/'
> 
> It is not clear to me what a trailing slash means, and especially why it is 
> needed on the left-hand side?
> 
> This is taken from the JavaScript importmap specification, but it exists to 
> cordon off direct file includes from directory includes. Original spec here: 
> https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap
>  
> And why slash here when namespaces use backslash?
> 
> Because it's the end of a path and unless you're on Windows directories are 
> delimited with /. They aren't the same thing
>  
> Also, as someone raised on DOS and then Windows only "converting" in 2009, I 
> still get confused in *nix when to use a trailing slash and when to not, so 
> this trailing slash worries me, if only for that reason alone.
> 
> I understand.  Here it's to call out that the key references a directory, not 
> a file. The value must explicitly be a directory, not a file, and a trailing 
> slash is the way that is done.  Files are not *required* to have extensions 
> after all.
> 
> Using the `@` here feels cryptic, and hard to discover and remember.
> 
> Perhaps, but this file is meant to be assembled by composer or some other 
> automated means - not by hand.  @ as a package operator is used in Node.js to 
> mark package namespaces - essentially the vendor of the package is marked 
> with @.  

I can tell your design here have been heavily influenced by your stated 
extensive experience with Node.js. Node.js' conventions probably seem second 
nature to you and thus easy for you to understand.

But for those us not steeped in Node.js, they are rather cryptic. Any time 
language designers chooses cryptic over obvious they place a large burden on 
learners and relatedly also on the experienced to deal with, correct and 
educate learners. For the languages targeting larger user bases like PHP — vs, 
say Haskell — the negative impact of cryptic can be widespread and costly in 
time spent and user base lost.  

So even if Node.js made the regrettable decision to choose cryptic over obvious 
I would implore anyone considering additions to PHP to side with obvious over 
cryptic. Even when said additions will often be automated, unless they will 
*always* be automated, such as the OpCache.

What does "obvious" mean here?  Assuming `.ini` files are use, then sections 
names that define usage, not special sigils.

> I think this would be infinitely easier to follow if packages were just 
> included in a `[packages]` section.
> 
> Packages will need to have some special handling though. 

Which does not preclude a special section for [packages].

> If, as Larry Gafield has stated, the engine cannot be made to maintain 
> multiple symbol tables, then the packages must be bound onto the master 
> symbol table.  

I have heard that repeatedly, but I have yet to hear *why*.  

PHP is just a C program, and clearly a C program can have multiple data 
structures.  Linux had a similar problem with filesystems and thus UnionFS was 
created. I'd really like to know why an equivalent architecture cannot be 
achieved with PHP's symbol table.

(If the reason why PHP "cannot be made to maintain multiple symbol tables" has 
been stated already, I could have easily missed it. If so and someone has a 
link to externals.io with the explanation, it would really appreciate that 
link.)

> But the legacy code in the package 

Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-07 Thread Arvids Godjuks
Q

On Sun, Jul 7, 2024, 03:03 Michael Morris  wrote:

>
>
>
>> 
>> ...
>> Many (most?) people on PHP Internals view WordPress coding standards as
>> bad and some even view addressing WordPress developers needs as bad for
>> PHP
>>
>
> I really don't want to get into that crossfire.  WordPress is the 800lb.
> gorilla of the PHP app world having more server market share that is
> dominant - how dominant depends on who you ask. The most conservative
> estimate I've seen is about half of PHP sites are running WordPress, and
> the most pro-WP quote I saw claimed it has around 80% share.
>
>

Automattic has chosen on purpose to be the way it is and they chosen to
rewrite everything into NodeJS, not that it will really help them anyway :)

>


Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-06 Thread Michael Morris
On Sat, Jul 6, 2024 at 2:12 AM Mike Schinkel  wrote:

> On Jul 5, 2024, at 1:47 PM, Michael Morris  wrote:
> I went to sleep thinking about this post, on import maps in general and
> how Composer works, specifically when you use a class map instead of the
> PSR-0 or PSR-4 schemes.  In that mode, Composer does pretty much what I've
> described.  This got me to thinking, could setting an import map be an
> alternative to setting an autoload function?  Would having the PHP runtime
> load the file be faster than mucking with some userland code to do the
> same? And would the engine be able to do anything that can't be done in
> userland?  I think so.
>
>
> I very much like this direction of thought.
>
> For context, when I worked with WordPress for about a decade I only ever
> used only Composer for websites but never for my own plugins, and I almost
> never used namespaces nor PSR-4 autoloaders for anything except when a
> plugin used them.  I almost exclusively used naming convensions for
> "namespacing" and classmaps for autoloading.
>

Some context from where I'm coming from.  I have been working exclusively
in React, NodeJS and Go up till about a year ago, and in Drupal before that
- it being 10 years since the last time I looked at WordPress. I need work
though, and I was offered a job where about two-thirds of my workload is a
massive WordPress site that has grown well outside the scope WordPress does
best.  So I've been getting used to it again and added some ulcers along
the way.


> Obviously I agree with having only one format, but not sure I concur with
> the use of .ini. However, me debating against `.ini` would be me
> bikeshedding and thus I will demure here.
>

I'm not married to ini either, but it will work for illustration. Adopting
another format will be one of the first decisions to make come
implementation.


> 
> ...
> Many (most?) people on PHP Internals view WordPress coding standards as
> bad and some even view addressing WordPress developers needs as bad for
> PHP
>

I really don't want to get into that crossfire.  WordPress is the 800lb.
gorilla of the PHP app world having more server market share that is
dominant - how dominant depends on who you ask. The most conservative
estimate I've seen is about half of PHP sites are running WordPress, and
the most pro-WP quote I saw claimed it has around 80% share.



>   ; A path fragment can be used, in which case PSR-4 will be used to map
> the rest of the symbol to the filename.
>
>   ; Pay attention to the direction of the slash at the tail - if the
> symbol key has this the value MUST also have this.
>   B/ = './path/to/B/'
>
>
> It is not clear to me what a trailing slash means, and especially why it
> is needed on the left-hand side?
>

This is taken from the JavaScript importmap specification, but it exists to
cordon off direct file includes from directory includes. Original spec
here:
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap


> And why slash here when namespaces use backslash?
>

Because it's the end of a path and unless you're on Windows directories are
delimited with /. They aren't the same thing


>
> Also, as someone raised on DOS and then Windows only "converting" in 2009,
> I still get confused in *nix when to use a trailing slash and when to not,
> so this trailing slash worries me, if only for that reason alone.
>

I understand.  Here it's to call out that the key references a directory,
not a file. The value must explicitly be a directory, not a file, and a
trailing slash is the way that is done.  Files are not *required* to have
extensions after all.



>
> Using the `@` here feels cryptic, and hard to discover and remember.
>

Perhaps, but this file is meant to be assembled by composer or some other
automated means - not by hand.  @ as a package operator is used in Node.js
to mark package namespaces - essentially the vendor of the package is
marked with @.


>
> I think this would be infinitely easier to follow if packages were just
> included in a `[packages]` section.
>

Packages will need to have some special handling though.  And the questions
I'm getting make that point increasingly clear.

If, as Larry Gafield has stated, the engine cannot be made to maintain
multiple symbol tables, then the packages must be bound onto the master
symbol table.  This presents a problem if multiple packages with different
versions are to be installed. One way to resolve this is some chicanery.
If PHP is instructed to install a file as a "package" it could load it onto
the symbol table in an auto-generated namespace - say \pkg_hash\Twig - and
then symbolic link to the package from other namespaces that are
referencing it.  Packages can (must) include other packages as their
dependencies.  If the symlinks are done right the end programmers do not
need to concern themselves with this implementation detail.

But the legacy code in the package itself needs to believe it is where it
expects to be 

Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-06 Thread Mike Schinkel
> On Jul 5, 2024, at 1:47 PM, Michael Morris  wrote:
> I went to sleep thinking about this post, on import maps in general and how 
> Composer works, specifically when you use a class map instead of the PSR-0 or 
> PSR-4 schemes.  In that mode, Composer does pretty much what I've described.  
> This got me to thinking, could setting an import map be an alternative to 
> setting an autoload function?  Would having the PHP runtime load the file be 
> faster than mucking with some userland code to do the same? And would the 
> engine be able to do anything that can't be done in userland?  I think so.

I very much like this direction of thought.

For context, when I worked with WordPress for about a decade I only ever used 
only Composer for websites but never for my own plugins, and I almost never 
used namespaces nor PSR-4 autoloaders for anything except when a plugin used 
them.  I almost exclusively used naming convensions for "namespacing" and 
classmaps for autoloading. 

Why? Was it because I was a "bad" programmer?  No, it was because when in Rome, 
you do as the Romans do.  And also because when I tried to use Composer and 
PSR-4 I was always fighting when them to do things in the way that worked best 
for WordPress.

Or to use a more modern analogy to PHP and WordPress, even though you may be 
landlocked by the country of Italy, if you are within the borders of Vatican 
City you follow the laws and conventions of Vatican City when they conflict 
with those of Italy.

> So first, I agree that supporting two formats, while convenient, increases 
> the maintenance burden, so let's just go with ini.  As far as the installing 
> function - a better name is this.

Obviously I agree with having only one format, but not sure I concur with the 
use of .ini. However, me debating against `.ini` would be me bikeshedding and 
thus I will demure here.

> spl_autoload_map( string $filepath );

Adding an `spl_autoload_map()` function and feature really resonates with me.  
As I said, I (almost?) always used class maps with WordPress so if I were to 
build another WordPress site with a future PHP that made an 
`spl_autoload_map()` available, I would TOTALLY use it.



Reading this however caused me to ponder things certain people has said 
recently — and many people have said for years on this list — and I think I am 
recognizing something that I have always known but never put the pieces 
together before.

Many (most?) people on PHP Internals view WordPress coding standards as bad and 
some even view addressing WordPress developers needs as bad for PHP. And in 
general I concur that those people are reasonably justified in their belief 
WordPress' coding standards are not the standards that PHP developer who want 
to do professional level software engineering should aspire. 

And since many (most?) PHP Internals members generally do not experience the 
issues that WordPress developers have they do not recognize that they are 
issues; IOW, "out of sight, out of mind." 

I also think some list members tend to dismiss WordPress developers pains as 
unimportant and/or think that addressing those pains have will harm PHP. 

(BTW, I recently had a dialog off-list with someone who wrote in an email that 
"Wordpress is an exception, but nobody these days treats WordPress as a valid 
example to do anything. It is an ancient piece of legacy code that has no 
bearing on modern situation and it's their problem to deal with." So I am not 
just erecting a straw man here.)

But I think what most may not consciously recognize is that WordPress is a 
different type of web app than an app build using Symfony or Laravel and 
deployed by its developers, or by some other professional developer. 

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 

Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-05 Thread Michael Morris
On Fri, Jul 5, 2024 at 2:23 PM Dusk  wrote:

>
> To that end - consider the following. Let's say that two different files
> in your project import different versions of package Foo. Foo contains a
> definition of the FooBar class, and contains functions which return that
> object.
>
> 1) If $foobar is one of those FooBar objects, what does $foobar::class
> return?


Depends on where it was imported to.  The current system ALWAYS imports to
the root namespace. This new system can import there, but also to another
namespace.  This was outlined in my previous email.

For @A\Foo\FooBar the import will put FooBar at \A\Foo\FooBar, and that's
what class will return.  @B\Foo\FooBar will bind it to \B\Foo\FooBar and
that will be the return of the class constant within the class.



> Is it the same as the fully qualified name of FooBar (e.g. "Foo\FooBar")?
> Does the result differ depending on what file contains that code?
>

Again, it depends on which package namespace the code was imported into.
Foo\FooBar isn't a fully qualified name even in current PHP. Fully
qualified names start with \, so the fully qualified name is \Foo\FooBar
provided it was included into the root namespace.


>
> 2) What happens if you try to pass that string back to something like new
> $class() or construct a ReflectionClass for it? Does that depend on the
> location of the call? What if the call is through something like
> PDO::FETCH_CLASS which occurs within the runtime?
>

Again, which package are we in?


>
> 3) Within Foo, would it be true that if $x = new FooBar(), then $x::class
> === FooBar::class?


Yes.


> Does this differ outside Foo (with an appropriately qualified name for
> FooBar)?
>

That's tricker, because the namespace matters in a way that it doesn't
matter now. Given an import mapping of "@A\FooBar" then

  namespace A;

  $x = new FooBar();
  $x::class === FooBar::class // true, however...
  echo $x::class //  \A\Foo\FooBar

That holds true even if FooBar's declaration file doesn't invoke any
namespace.


>
> 4) If those two files both create FooBar objects of their respective
> versions, what happens if you try to pass one of those objects to a
> function in the file using the "wrong" version of Foo? Does it pass type
> checks, and what happens if it does? If not, how does the check fail?
>

Each package has its own Foo\FooBar. They won't be interoperable even
though they arise from the same code. If they should be or need to be
interoperable then PHP will have to gain a notion of package beyond what's
been scoped out here.


> 5) What shows up in the output of functions like get_declared_classes()?
> Are there multiple instances of FooBar in there for each version? How are
> they distinguished from one another?


You'll get
\A\Foo\FooBar
\B\Foo\FooBar

If you also directly load Foo\FooBar into the root namespace using the
composer autoloader you could also see \Foo\FooBar


Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-05 Thread Dusk
On Jul 3, 2024, at 17:16, Michael Morris  wrote:
> Can PHP support multiple packages without rewriting the whole engine?  I 
> think so, but it isn't trivial, and the side effects need to be cordoned off 
> so that those who need this complexity can have it while the beginning and 
> intermediate coders can ignore it just like they ignore strict comparison 
> operators and strict typing unless a library they are trying to use foists it 
> on them.

I think that focusing on the syntax and tooling for executing these imports is 
starting at the wrong end of this problem. The bulk of the work for this 
feature is going to be whatever engine changes are required to support 
versioning, not the tooling around it.

To that end - consider the following. Let's say that two different files in 
your project import different versions of package Foo. Foo contains a 
definition of the FooBar class, and contains functions which return that object.

1) If $foobar is one of those FooBar objects, what does $foobar::class return? 
Is it the same as the fully qualified name of FooBar (e.g. "Foo\FooBar")? Does 
the result differ depending on what file contains that code?

2) What happens if you try to pass that string back to something like new 
$class() or construct a ReflectionClass for it? Does that depend on the 
location of the call? What if the call is through something like 
PDO::FETCH_CLASS which occurs within the runtime?

3) Within Foo, would it be true that if $x = new FooBar(), then $x::class === 
FooBar::class? Does this differ outside Foo (with an appropriately qualified 
name for FooBar)?

4) If those two files both create FooBar objects of their respective versions, 
what happens if you try to pass one of those objects to a function in the file 
using the "wrong" version of Foo? Does it pass type checks, and what happens if 
it does? If not, how does the check fail?

5) What shows up in the output of functions like get_declared_classes()? Are 
there multiple instances of FooBar in there for each version? How are they 
distinguished from one another?

Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-05 Thread Michael Morris
On Fri, Jul 5, 2024 at 1:29 AM Mike Schinkel  wrote:

> On Jul 4, 2024, at 9:16 PM, Michael Morris  wrote:
> On Wed, Jul 3, 2024 at 11:11 PM Mike Schinkel  wrote:
>
>> So I've had more time to mull this over, and some research, and I think I
>> have an approach.
>
>
> First, instead of 'import', use 'require_module'.  The parsing rules for
> require_module differ from require how the file is parsed, a subject for
> another time.  Also, it's parallel to what is to follow.
>
>
> +1
>
> Speaking of new functions, let's start with these
>
>   spl_set_include_ini_map('importmap.ini');
>   spl_set_include_json_map('importmap.json")
>
>
> Those are a mouthful!
>
> The json file is pretty much identical to the JavaScript importmaps. The
> ini file looks like this
>
>   root = "/absolute/path/to/application/root"
>
>   [imports]
>   square = "./path/to/square.js"
>   circle = "./path/to/circle.js"
>   other/ = "./path/to/other/"
>
>   [scopes]
>   \A[square] = './path/to/square/in/namespace/A/a.js'
>
>
> I assume rather than `.js` you mean `.php` files in your example?
>
> Also, I am not following how these imports and scopes will relate to the
> actual PHP code that would be affected/using packages.
>
> Whichever format is used is a matter of personal preference. The file can
> be, and likely should be, written by composer or some future package
> manager.
>
>
> Part of me likes the flexibility of two formats. The other more pragmatic
> part of me says stick with one format for fewer related bugs and to reduce
> the effort to support it for internal code and by 3rd parties.
>
> Unless it can be fully cached by opcache I would think it would need to be
> the format that can be parsed the fastest, which could be binary like a
> Protobuf file.
>
> The root attribute in the map sets the root for all relative paths given
> in the map.
>
>
> Are you saying that a publisher of a package would need to write the
> absolute path to their `importmap.*` file. How will that work?  Even for a
> bespoke app Composer may not have enough access to the server to know this,
> and 3rd party packages will definitely not know it for their users. At
> least I don't think so.
>
> Also, at this point trying to keep track of all your ideas is impossible,
> at least for me. Have you reconsidered putting it in a repo or at least a
> Gist yet so it is easier to see the scope of your current ideas about
> packages?
>
>
I'm getting there. I'm trying to boil things down at this point to
something that can be put into such.

I went to sleep thinking about this post, on import maps in general and how
Composer works, specifically when you use a class map instead of the PSR-0
or PSR-4 schemes.  In that mode, Composer does pretty much what I've
described.  This got me to thinking, could setting an import map be an
alternative to setting an autoload function?  Would having the PHP runtime
load the file be faster than mucking with some userland code to do the
same? And would the engine be able to do anything that can't be done in
userland?  I think so.

So first, I agree that supporting two formats, while convenient, increases
the maintenance burden, so let's just go with ini.  As far as the
installing function - a better name is this.

spl_autoload_map( string $filepath );

This function will register an autoload map wrapped with an internal
autoloader to work with it.  If called multiple times the maps will resolve
in the order they are called.  If called along with the existing
spl_autoload_register function then the maps and autoload functions will be
used in the order of their declaration. Packages are expected to carry
their own autoload maps.  Autoload maps can only be loaded once - attempts
to load the same map multiple times will raise a E_USER_WARNING

The contents of the file along with comments as to what they do.

  ; The root directive affects the relative paths in the map.  If set the
location specified becomes
  ; the root. If not set all relative paths are relative to THIS FILE.
  ;root = '/some/path'

  ; If a package is declared, that is the root namespace for all the
includes that follow.
  ; As this example is for a root autoloader it is commented out, as the
root autoload function of
  ; an app doesn't need a package name.
  ;package =

  ; A map relates symbols to files. This one is for the existing
include/require system. Actual
  ; file loading is performed by require_once.
  [includes]
  A\B\Cat = './path/to/Cat.php'

  ; A symbol can invoke the loading of multiple files. This will be useful
if the package manager that
  ; prepares this file determines that a polyfill will be needed. Files
will be loaded in order given.
  A\TestClass[] = './path/to/polyfill.php'
  A\TestClass[] = './path/to/TestClass.php'

  ; A wildcard can be used if there is a desire to pack multiple symbols
together
  ; Note the path with the most specific match wins here, so \A\foo() will
invoke the autoload below,
  ; but \A\TestClass or \A\B\Cat will 

Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-04 Thread Mike Schinkel
> On Jul 4, 2024, at 9:16 PM, Michael Morris  wrote:
> On Wed, Jul 3, 2024 at 11:11 PM Mike Schinkel  > wrote:
> So I've had more time to mull this over, and some research, and I think I 
> have an approach.
> 
> First, instead of 'import', use 'require_module'.  The parsing rules for 
> require_module differ from require how the file is parsed, a subject for 
> another time.  Also, it's parallel to what is to follow.

+1 

> Speaking of new functions, let's start with these
> 
>   spl_set_include_ini_map('importmap.ini');
>   spl_set_include_json_map('importmap.json")

Those are a mouthful! 

> The json file is pretty much identical to the JavaScript importmaps. The ini 
> file looks like this
> 
>   root = "/absolute/path/to/application/root"
> 
>   [imports]
>   square = "./path/to/square.js"
>   circle = "./path/to/circle.js"
>   other/ = "./path/to/other/"
> 
>   [scopes]
>   \A[square] = './path/to/square/in/namespace/A/a.js'

I assume rather than `.js` you mean `.php` files in your example?

Also, I am not following how these imports and scopes will relate to the actual 
PHP code that would be affected/using packages.

> Whichever format is used is a matter of personal preference. The file can be, 
> and likely should be, written by composer or some future package manager.

Part of me likes the flexibility of two formats. The other more pragmatic part 
of me says stick with one format for fewer related bugs and to reduce the 
effort to support it for internal code and by 3rd parties.

Unless it can be fully cached by opcache I would think it would need to be the 
format that can be parsed the fastest, which could be binary like a Protobuf 
file.

> The root attribute in the map sets the root for all relative paths given in 
> the map.

Are you saying that a publisher of a package would need to write the absolute 
path to their `importmap.*` file. How will that work?  Even for a bespoke app 
Composer may not have enough access to the server to know this, and 3rd party 
packages will definitely not know it for their users. At least I don't think so.

Also, at this point trying to keep track of all your ideas is impossible, at 
least for me. Have you reconsidered putting it in a repo or at least a Gist yet 
so it is easier to see the scope of your current ideas about packages?

-Mike



Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-04 Thread Michael Morris
On Wed, Jul 3, 2024 at 11:11 PM Mike Schinkel  wrote:

> >>   import 'file.php v1.0.0';
> >
> > Where will PHP be able to get the version number in a performant manner?
> >
> > A question for another day.
>
> Frankly if your proposal hinges on using version numbers to differentiate
> then I think it is not something you can postpone answering.
>
> If there is not a good answer then the approach you are exploring is moot,
> at least as far as I can see.
>
>
So I've had more time to mull this over, and some research, and I think I
have an approach.

First, instead of 'import', use 'require_module'.  The parsing rules for
require_module differ from require how the file is parsed, a subject for
another time.  Also, it's parallel to what is to follow.

Speaking of new functions, let's start with these

  spl_set_include_ini_map('importmap.ini');
  spl_set_include_json_map('importmap.json")

The json file is pretty much identical to the JavaScript importmaps. The
ini file looks like this

  root = "/absolute/path/to/application/root"

  [imports]
  square = "./path/to/square.js"
  circle = "./path/to/circle.js"
  other/ = "./path/to/other/"

  [scopes]
  \A[square] = './path/to/square/in/namespace/A/a.js'

Whichever format is used is a matter of personal preference. The file can
be, and likely should be, written by composer or some future package
manager.

The root attribute in the map sets the root for all relative paths given in
the map.

Imports are the standard imports for the project.  The token on the left
maps to the target on the right.
Import maps affect all includes.  Import map tokens are considered before
anything use on the include resolution rules.  So `include 'square'` would
bring in '/absolute/path/to/application/root/path/to/square.js' given the
ini file above.

An import token ending in / is a prepend and the path it maps to must also
end in a slash.  So `require_module 'other/triangle.php' will map to
'/absolute/path/to/application/root/path/to/other/triangle.php' given the
ini file above.

Scopes have a namespace followed by the token in brackets.  Scopes only
affect require_module as the other include mechanisms do not pay attention
to namespaces.  When in that namespace the specified file will be loaded
instead of the default outlined in imports.

The import map system is inspired by but not exactly like JavaScript's
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap

This approach gets whatever RFC that comes out of this proposal out of the
business of trying to design a package manager.


Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-04 Thread Mike Schinkel


> On Jul 4, 2024, at 3:05 PM, Chuck Adams  wrote:
> 
>> On Jul 4, 2024, at 12:02 PM, Mike Schinkel  wrote:
>> 
>> The point being that PHP is free to choose how they are defined with respect 
>> to PHP.
>> 
>> To which I will add "as long as the terms are used consistently.”
> 
> ...but whatever makes sense for PHP is what’s best. 

Definitely.

-Mike


Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-04 Thread Chuck Adams


> On Jul 4, 2024, at 12:02 PM, Mike Schinkel  wrote:
> 
> Your definitions are language-specific.  For example, in Go the definitions 
> for those terms are the opposite of how you defined them.
> 
> The point being that PHP is free to choose how they are defined with respect 
> to PHP.
> 
> To which I will add "as long as the terms are used consistently.”


Okay, some languages may swap the terms, others like JS glom the concepts 
together, and in Perl 5 “package Foo” defines a module.  I’d say most PHP devs 
are more familiar with the terms as they’re used in JS, but whatever makes 
sense for PHP is what’s best.  I suppose I do have a dog in the fight, but I 
don’t much care how it’s groomed.  

Then there’s GHC Haskell which has `import “package-name” 
ModuleName.{Foo,Bar,Baz}`, which seems to cover all the bases.  Decent ideas 
from the syntax, but I don’t think I want to replicate backpack :)

—c


Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-04 Thread Mike Schinkel
Hi Chuck,

> On Jul 4, 2024, at 11:05 AM, Chuck Adams  wrote:
>> On Jul 3, 2024, at 6:16 PM, Michael Morris  wrote:
>> 
>> Hello all. Hitting reset again as the primary problem at hand has become 
>> clear.  Let's recap it.
>> 
>> Autoloading is great for loading packages, but it can't load different 
>> versions of the same package at the same time.  Why would you want to do 
>> that?
>> 
>> When you don't have full control of the code.in 
>> 
>> For example, consider Drupal.  It is running Twig at some version of 3 at 
>> the moment. Suppose Twig 4 is introduced with significant backward 
>> compatibility breaks (Not saying the authors would do such a thing) but also 
>> wonderful features.
>> …[snip]...
>> This is why I advocate a new keyword for this - import.  Import’s behavior 
>> is most similar to require_once, but it doesn't have to be the same.  Since 
>> it is a new entrypoint into the engine the way the engine considers the code 
>> can be different - whether slightly different or radically different is a 
>> debate for another time. I'm going to stick with only those changes that 
>> make sense in the context of package links.
> 
> 
> I’m seeing a lot of conflation of ‘module’ and ‘package’ in these 
> discussions, and to me they mean different things:
> 
> * A module is a sort of “first class namespace” that can export symbols and 
> import others.  Think ES5 or python modules.  If you don’t want it 1-1 with 
> files, think Perl modules.
> 
> * A package is an “installable” unit that provides modules, among other 
> things.  Packages have metadata, the most important piece of which is a 
> machine-readable version.

Your definitions are language-specific.  For example, in Go the definitions for 
those terms are the opposite of how you defined them.

The point being that PHP is free to choose how they are defined with respect to 
PHP.  

To which I will add "as long as the terms are used consistently."

-Mike

Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-04 Thread Chuck Adams



> On Jul 3, 2024, at 6:16 PM, Michael Morris  wrote:
> 
> Hello all. Hitting reset again as the primary problem at hand has become 
> clear.  Let's recap it.
> 
> Autoloading is great for loading packages, but it can't load different 
> versions of the same package at the same time.  Why would you want to do that?
> 
> When you don't have full control of the code.
> 
> For example, consider Drupal.  It is running Twig at some version of 3 at the 
> moment. Suppose Twig 4 is introduced with significant backward compatibility 
> breaks (Not saying the authors would do such a thing) but also wonderful 
> features.
> …[snip]...
> This is why I advocate a new keyword for this - import.  Import’s behavior is 
> most similar to require_once, but it doesn't have to be the same.  Since it 
> is a new entrypoint into the engine the way the engine considers the code can 
> be different - whether slightly different or radically different is a debate 
> for another time. I'm going to stick with only those changes that make sense 
> in the context of package links.


I’m seeing a lot of conflation of ‘module’ and ‘package’ in these discussions, 
and to me they mean different things:

* A module is a sort of “first class namespace” that can export symbols and 
import others.  Think ES5 or python modules.  If you don’t want it 1-1 with 
files, think Perl modules.

* A package is an “installable” unit that provides modules, among other things. 
 Packages have metadata, the most important piece of which is a 
machine-readable version.

Certainly there’s overlap between the two, but the first is a more low-level 
thing that doesn’t need worry itself about versioning let alone multiple 
simultaneous versions.  I just don’t want to see the possibility of having 
basic “import” and “export” functionality crushed under the bikeshed while all 
the fine semantics of versioning are worked out.  

—c


Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-03 Thread Mike Schinkel
> On Jul 3, 2024, at 10:31 PM, Michael Morris  wrote:
> 
> On Wed, Jul 3, 2024 at 9:56 PM Mike Schinkel  wrote:
> 
> There are ~6300 uses of the keyword `import` on GitHub:  
> 
> https://github.com/search?q=import+language%3APHP+symbol%3A%2F%5Eimport%24%2F=code
> 
> That's a lot of BC breakage for some people.
> 
> No worse than PHP 7's keyword introductions.

True. 

OTOH, if you don't actually have to break BC for discretionary changes, then it 
would be better not to.

>> Import's behavior is most similar to require_once, but it doesn't have to be 
>> the same.  Since it is a new entrypoint into the engine the way the engine 
>> considers the code can be different - whether slightly different or 
>> radically different is a debate for another time. I'm going to stick with 
>> only those changes that make sense in the context of package links.
> 
> When you first proposed modules I was understood (wrongly?) that you were 
> proposing imports to be a statement that imported into file scope and then at 
> the end of loading the file PHP would flush those symbols just like how (I 
> think?) JavaScript imports work (I am ignoring the complexity closures add to 
> simplify our discussion here.)
> 
> That was the first iteration, yes.  I am adjusting to the feedback on the 
> list.  JavaScript does imports the way it does because of how files scope, 
> and how the module system itself scopes, which isn't readily retrofitted onto 
> PHP.

I think it *can* be retrofitted to PHP, but that is a different issue and I 
won't derail your discussion to suggest it in this thread.

> Also, at the time I was toying around with the format and had yet to hit upon 
> the situation where it could be useful, that being versioned files.
>  
> This sounds like you are saying `import` would (instead?) be dynamic like 
> `include*` and `require*` and any symbols loaded with `import` would continue 
> their lifetime until the program is finished or the page is loaded, depending 
> on how the program is run?
> 
> Yes, because that is how PHP itself does work under the hood, at least for 
> php file includes. How it would go about doing this when resolving .so or 
> .dll extensions is another matter.  Does it have to be this way? That's the 
> hint I've gotten from the feedback but only a core contributor with 
> experience working on the engine could say for sure.
>  
> I ask because when I was envisioning page scope being added to PHP I was also 
> envisioning that PHP could perform more optimizations if the new symbols only 
> affected the currently loaded page. If you are proposing beyond-page lifetime 
> then that precludes this optimizations which is not a deal killer but is a 
> disappointment.
> 
> Whether the optimizations affect the file on load depends on what's being 
> optimized to be honest. There is still an opportunity here.

Where do you see opportunity for optimization — assuming your vision of imports 
— that is not already a potential for optimization?

>  
>> Now we have \B\foo();  This makes it relatively easy to have two different 
>> versions of the package running since in our own code we can always 
>> reference the foo in the B namespace. But while that allows limited package 
>> versioning, it doesn't solve the multiple extensions wanting to use the new 
>> stuff problem outlined above.
> 
> Consider the following parts of an application:
> 
> 1. Bespoke app
> 2. "Enterprise Reports" library
> 3. Twig v3 used by "Enterprise Reports"
> 4. "ProductsPro" library
> 5. Twig v4 used by "ProductsPro"
> 6. "PP2ER Connector" library
> 
> Given your scenario I guess you assume Enterprise Reports would import Twig 
> v3 as maybe `ER\Twig` and ProductsPro would import Twig v4 as maybe 
> `PP\Twig`, right?
> 
> Correct.
>  
> 
> How does the PP2ER Connector use Twig?  
> 
> Depends on which one it wishes to use, \ER\Twig or \PP\Twig
>  
> Does it create it own `PP2ER\Twig`?  What if the connector needs to use the 
> `ER\Twig\Environment` from ProductsPro with the 
> `Twig\Loader\FilesystemLoader` from Enterprise Reports where those classes 
> have private and protected properties that are simple not composable, and 
> especially not across versions.
> 
> I've never seen cross version mixing like you're describing so I didn't take 
> it into account. That said, the extant copies of those classes will be 
> variables, and hopefully not global variables.

I have with WordPress plugins. 

I wish I could say exactly what, where and when, but sadly that knowledge was 
lost to the mists of time.

> Or what it he app itself needs to use the functionality of both in a way that 
> requires access to `private` and/or `protected` property values or methods 
> across the two versions?
> 
> That isn't in scope for this discussion. The whole point of private and 
> protected scope modifiers is to restrict access by outside code. Breaking 
> through that can be done with the Reflection API in some cases, but it isn't 
> easy.

I 

Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-03 Thread Michael Morris
On Wed, Jul 3, 2024 at 9:56 PM Mike Schinkel  wrote:

>
> There are ~6300 uses of the keyword `import` on GitHub:
>
>
> https://github.com/search?q=import+language%3APHP+symbol%3A%2F%5Eimport%24%2F=code
> 
>
> That's a lot of BC breakage for some people.
>
>
No worse than PHP 7's keyword introductions.


> Import's behavior is most similar to require_once, but it doesn't have to
> be the same.  Since it is a new entrypoint into the engine the way the
> engine considers the code can be different - whether slightly different or
> radically different is a debate for another time. I'm going to stick with
> only those changes that make sense in the context of package links.
>
>
> When you first proposed modules I was understood *(wrongly?)* that you
> were proposing imports to be a statement that imported into file scope and
> then at the end of loading the file PHP would flush those symbols just like
> how *(I think?)* JavaScript imports work *(I am ignoring the complexity
> closures add to simplify our discussion here.)*
>

That was the first iteration, yes.  I am adjusting to the feedback on the
list.  JavaScript does imports the way it does because of how files scope,
and how the module system itself scopes, which isn't readily retrofitted
onto PHP. Also, at the time I was toying around with the format and had yet
to hit upon the situation where it could be useful, that being versioned
files.


> This sounds like you are saying `import` would *(*instead*?)* be dynamic
> like `include*` and `require*` and any symbols loaded with `import` would
> continue their lifetime until the program is finished or the page is
> loaded, depending on how the program is run?
>

Yes, because that is how PHP itself does work under the hood, at least for
php file includes. How it would go about doing this when resolving .so or
.dll extensions is another matter.  Does it have to be this way? That's the
hint I've gotten from the feedback but only a core contributor with
experience working on the engine could say for sure.


> I ask because when I was envisioning page scope being added to PHP I was
> also envisioning that PHP could perform more optimizations if the new
> symbols only affected the currently loaded page. If you are proposing
> beyond-page lifetime then that precludes this optimizations which is not a
> deal killer but is a disappointment.
>

Whether the optimizations affect the file on load depends on what's being
optimized to be honest. There is still an opportunity here.


> Now we have \B\foo();  This makes it relatively easy to have two different
> versions of the package running since in our own code we can always
> reference the foo in the B namespace. But while that allows limited package
> versioning, it doesn't solve the multiple extensions wanting to use the new
> stuff problem outlined above.
>
>
> Consider the following parts of an application:
>
> 1. Bespoke app
> 2. "Enterprise Reports" library
> 3. Twig v3 used by "Enterprise Reports"
> 4. "ProductsPro" library
> 5. Twig v4 used by "ProductsPro"
> 6. "PP2ER Connector" library
>
> Given your scenario I guess you assume Enterprise Reports would import
> Twig v3 as maybe `ER\Twig` and ProductsPro would import Twig v4 as maybe
> `PP\Twig`, right?
>

Correct.


>
> How does the PP2ER Connector use Twig?
>

Depends on which one it wishes to use, \ER\Twig or \PP\Twig


> Does it create it own `PP2ER\Twig`?  What if the connector needs to use
> the `ER\Twig\Environment` from ProductsPro with the
> `Twig\Loader\FilesystemLoader` from Enterprise Reports where those classes
> have private and protected properties that are simple not composable, and
> especially not across versions.
>

I've never seen cross version mixing like you're describing so I didn't
take it into account. That said, the extant copies of those classes will be
variables, and hopefully not global variables.


>
> Or what it he app itself needs to use the functionality of both in a way
> that requires access to `private` and/or `protected` property values or
> methods across the two versions?
>

That isn't in scope for this discussion. The whole point of private and
protected scope modifiers is to restrict access by outside code. Breaking
through that can be done with the Reflection API in some cases, but it
isn't easy.


>
> So we have to call out the version in code, like so.
>
>   import 'file.php v1.0.0';
>
>
> Where will PHP be able to get the version number in a performant manner?
>

A question for another day. I'm not going to touch on it yet as I want
feedback on the rest of what I've written in this iteration first and,
honestly, I want to mull it over in my head a little more. It may be that
the code doesn't have the version number but the package declaration file
does. There definitely would be advantages to that, but it may still be
desirable to have the version called out in the import statement in code.


Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-03 Thread Mike Schinkel
> On Jul 3, 2024, at 8:16 PM, Michael Morris  wrote:
> Can PHP support multiple packages without rewriting the whole engine?  I 
> think so, but it isn't trivial, and the side effects need to be cordoned off 
> so that those who need this complexity can have it while the beginning and 
> intermediate coders can ignore it just like they ignore strict comparison 
> operators and strict typing unless a library they are trying to use foists it 
> on them.
> 
> This is why I advocate a new keyword for this - import. 

There are ~6300 uses of the keyword `import` on GitHub:  

https://github.com/search?q=import+language%3APHP+symbol%3A%2F%5Eimport%24%2F=code
 

That's a lot of BC breakage for some people.

For this proposal, would one of these not be acceptable instead (assuming that 
the compiler could handle `import` in this way w/o it being a new reserved 
word)?:

```
include "file.php" as import
use import "file.php"
```

> Import's behavior is most similar to require_once, but it doesn't have to be 
> the same.  Since it is a new entrypoint into the engine the way the engine 
> considers the code can be different - whether slightly different or radically 
> different is a debate for another time. I'm going to stick with only those 
> changes that make sense in the context of package links.

When you first proposed modules I was understood (wrongly?) that you were 
proposing imports to be a statement that imported into file scope and then at 
the end of loading the file PHP would flush those symbols just like how (I 
think?) JavaScript imports work (I am ignoring the complexity closures add to 
simplify our discussion here.)

This sounds like you are saying `import` would (instead?) be dynamic like 
`include*` and `require*` and any symbols loaded with `import` would continue 
their lifetime until the program is finished or the page is loaded, depending 
on how the program is run?

I ask because when I was envisioning page scope being added to PHP I was also 
envisioning that PHP could perform more optimizations if the new symbols only 
affected the currently loaded page. If you are proposing beyond-page lifetime 
then that precludes this optimizations which is not a deal killer but is a 
disappointment.

> Now we have \B\foo();  This makes it relatively easy to have two different 
> versions of the package running since in our own code we can always reference 
> the foo in the B namespace. But while that allows limited package versioning, 
> it doesn't solve the multiple extensions wanting to use the new stuff problem 
> outlined above.

Consider the following parts of an application:

1. Bespoke app
2. "Enterprise Reports" library
3. Twig v3 used by "Enterprise Reports"
4. "ProductsPro" library
5. Twig v4 used by "ProductsPro"
6. "PP2ER Connector" library

Given your scenario I guess you assume Enterprise Reports would import Twig v3 
as maybe `ER\Twig` and ProductsPro would import Twig v4 as maybe `PP\Twig`, 
right?

How does the PP2ER Connector use Twig?  Does it create it own `PP2ER\Twig`?  
What if the connector needs to use the `ER\Twig\Environment` from ProductsPro 
with the `Twig\Loader\FilesystemLoader` from Enterprise Reports where those 
classes have private and protected properties that are simple not composable, 
and especially not across versions.

Or what it he app itself needs to use the functionality of both in a way that 
requires access to `private` and/or `protected` property values or methods 
across the two versions?

> So we have to call out the version in code, like so.
> 
>   import 'file.php v1.0.0';

Where will PHP be able to get the version number in a performant manner, 
remembering that the problem to be solved is dependencies of dependencies so 
you cannot rely on a strict directory structure with version numbers unless a 
non-PSR4 autoloader format is introduced and widely adopted?

Will packages need to ship `composer.lock` and developers deploy them? Will 
that be performant and secure enough?

What about libraries and packages that do not use Composer?  How will WordPress 
handle this with plugin dependencies?

-Mike