On 04/05/2025 08:34, Michael Morris wrote:
PHP has no way of dealing with userland code trying to write to the
same entry
on the symbol tables. Namespaces are a workaround of this and
combined with
autoloaders they've yielded the package environments we currently have
(usually
composer), but at the end of the day if two code blocks want different
versions
of the same package invoked at the same time there's going to be a
crash. This
is seen most visibly in WordPress plugins that use composer, as they
resort to
monkey-typing the composer packages they consume to avoid such collisions.
I think there are two different problems being muddled here:
1) How can two *completely unrelated* libraries avoid *accidentally*
declaring something with the same name?
2) How can two versions of *the same* library be used in different parts
of the same running program, despite overlapping names?
Namespaces are not a workaround to problem number 2, they are a solution
to problem number 1: every library chooses a prefix, and avoids
declaring symbols with prefixes used by other libraries.
Problem number 2 is what you seem to be trying to address.
In languages like EcmaScript/JavaScript/TypeScript, the solution (to
both problems) is to say that declarations don't have a canonical name.
They're values that you can pass around, and their name is whatever a
local scope says it is. This has major implications on both the language
and its ecosystem:
- contracts between libraries need to be structural, because there is no
name that all libraries agree on for an interface/protocol/whatever
- package managers don't resolve the graph of dependencies to a
consistent set, they install multiple copies of the same library, for
use in different scopes
- package authors are free to depend on mutually incompatible concrete
implementations, rather than agreed or de facto standards and interfaces
NPM is notorious for creating a giant directory of tiny modules, because
that's what the language design encourages.
That's not how PHP works, and it never will be. In PHP (and other
languages like Java, and C#), declarations have a single fully-qualified
name. If you want two different versions of the same library, you will
need to find a way to make their declarations use different
fully-qualified names.
Most applications do not have this problem. In fact, I would say that
most applications would actively suffer from having multiple copies of
the same library installed.
The main exception, as you have pointed out, is plugin architectures
like WordPress, where the plugin might want to "privately" use some
library without impacting the host application and other plugins. For
those, userland solutions already exist - a random search turned up this
one, which lists some alternatives:
https://github.com/BrianHenryIE/strauss?tab=readme-ov-file#alternatives
I *do* think PHP would benefit from some native concept of "module" for
other reasons, e.g. marking internal components, optimising across
multiple files. I *do not* think that ES/JS/TS is a suitable model to
look at, because it is starting from a fundamentally different concept
of what a declaration is.
I also *do not* think that allowing multiple versions of the same
library should be a core requirement of any native module support;
enabling userland to achieve it efficiently would be a nice to have.
--
Rowan Tommins
[IMSoP]