On 02/06/2025 17:57, Larry Garfield wrote:
Well, now you're talking about something with a totally separate compile step,
which is not what Michael seemed to be describing at all. But it seems like
that would be necessary.
There's definitely some crossed wires somewhere. I deliberately left the
mechanics vague in that last message, and certainly didn't mention any
specific compiler steps. I'm a bit lost which part you think is "not
what Michael seemed to be describing".
Picking completely at random, a file in Monolog has these lines in:
namespace Monolog\Handler;
...
use Monolog\Utils;
...
class StreamHandler extends AbstractProcessingHandler {
...
$this->url = Utils::canonicalizePath($stream);
My understanding is that our goal is to allow two slightly different
copies of that file to be included at the same time. As far as I know,
there have been two descriptions of how that would work:
a) Before or during compilation, every reference is automatically
prefixed, so that the class is declared as
"\__SomeMagicPrefix\Monolog\Handler\StreamHandler", and the reference to
"\Monolog\Utils" is replaced by a reference to
"\__SomeMagicPrefix\Monolog\Utils". There are existing userland
implementations that take this approach.
b) While the class is being compiled, PHP swaps out the entire symbol
table, so that the class is still called
"\Monolog\Handler\StreamHandler", and the reference to "\Monolog\Utils"
is to the class of that name in the current symbol table. In a different
symbol table, both names refer to separately compiled classes.
The "new namespace root" in my last message is either (a) the special
prefix, or (b) the actual root of the new symbol table. In either case,
you need to decide which classes to declare under that root; either
recursively tracking what requires what, or just where on disk the file
was loaded from.
Even if we're willing to require the authors of Monolog to rewrite their
library for the convenience of WordPress plugin authors, I don't see how
we can get away from every class in PHP being fundamentally identified
by name, and the compiler needing to manage those names somehow.
We can imagine a parallel universe where PHP declarations worked like JS
or Python:
import * from Monolog\Handler;
...
$Utils = import Monolog\Utils;
...
$StreamHandler = class extends $AbstractProcessingHandler {
...
$this->url = $Utils::canonicalizePath($stream);
But at that point, we're just inventing a new programming language.
At which point, we're basically talking about "load this Phar file into a custom
internalized namespace", which, from my limited knowledge of Phar, seems like the
most logical way to do it. That also sidesteps all the loading and linking shenanigans.
I don't think Phar files would particularly help. As far as I know,
they're just a file system wrapper; you still have to include/require
the individual files inside the archive, and they're still compiled in
exactly the same way.
Whether we want to isolate "any definition you find in the directory
/var/www/wordpress/wp-plugins/foo/" or "any definition you find in the
Phar archive phar:///var/www/wordpress/wp-plugins/foo.phar", the tricky
part is how to do the actual isolating.
--
Rowan Tommins
[IMSoP]