On 22/05/2025 12:09, Michael Morris wrote:
I've tried several times to explain why I think Linux containers
are a good analogy; I'm not sure if you didn't understand, or just
didn't agree, so I don't know what else I can say.
I have no disagreement with that, but it's an implementation detail.
I'm not there yet - I'm just trying to describe what I think is needed
from outside the engine.
I think this is where we're not seeing eye to eye, and why we're getting
frustrated with each other, because I see it as far more fundamental
than details you have already gone into, like how autoloading will work.
Perhaps a more realistic example will help, and also avoid the confusion
over "A, B, and D" from earler.
Imagine a WordPress plugin, AlicesCalendar, which uses the Composer
packages monolog/monolog and google/apiclient. The google/apiclient
package also requires monolog/monolog.
Another WordPress plugin, BobsDocs, also uses both monolog/monolog and
google/apiclient, but using different versions.
Inside those different places, there are lines of code like this:
$logger = new \Monolog\Logger('alices-calendar'); // in AlicesCalendar
$logger = new \Monolog\Logger('bobs-docs'); // in BobsDocs
$logger = new \Monolog\Logger('google-api-php-client'); // in
google/apiclient
We need to rewrite those lines so that they all refer to the correct
version of Monolog\Logger.
If every package/module/whatever rewrites the classes inside every other
package/module/whatever, we might start with this:
$logger = new \AlicesCalendar\Monolog\Logger('alices-calendar'); // in
AlicesCalendar
$logger = new \BobsDocs\Monolog\Logger('bobs-docs'); // in BobsDocs
$logger = new \GoogleApiClient\Monolog\Logger('google-api-php-client');
// in google/apiclient
That only works if we somehow know that AlicesCalendar and BobsDocs use
the same google/apiclient; if not, we need four copies:
$logger = new \AlicesCalendar\Monolog\Logger('alices-calendar'); // in
AlicesCalendar
$logger = new
\AlicesCalendar\GoogleApiClient\Monolog\Logger('google-api-php-client');
// in google/apiclient when called from AlicesCalendar
$logger = new \BobsDocs\Monolog\Logger('bobs-docs'); // in BobsDocs
$logger = new
\BobsDocs\GoogleApiClient\Monolog\Logger('google-api-php-client'); // in
google/apiclient when called from BobsDocs
All of these are separate classes, which can't be used interchangeably,
and the names get longer and longer to isolate dependencies inside
dependencies.
But we don't actually need the Monolog\Logger used by AlicesCalendar to
be a different version from the one used by google/api-client. In fact,
it would be useful if they were the same, so we could pass around the
objects interchangeably *inside* the plugin code.
So what we want is some way of saying that AlicesCalendar and BobsDocs
are special; they want to isolate code in a way that normal
modules/packages/whatever don't. Then we can have 2 copies of
Monolog\Logger, not 3 or 4:
$logger = new \AlicesCalendar\Monolog\Logger('alices-calendar'); // in
AlicesCalendar
$logger = new \AlicesCalendar\Monolog\Logger('google-api-php-client');
// in google/apiclient when called from AlicesCalendar
$logger = new \BobsDocs\Monolog\Logger('bobs-docs'); // in BobsDocs
$logger = new \BobsDocs\Monolog\Logger('google-api-php-client'); // in
google/apiclient when called from BobsDocs
In this case, PHP doesn't need to know monolog/monolog even exists. It
just puts either "AlicesCalendar" or "BobsDocs" on any class name it sees.
Before we can even think about *how* we'd implement the rewriting (or
shadowing, or whatever) we need some requirements of *what* we want to
rewrite. By suggesting an image of "containers" or "sandboxes" rather
than "packages" or "modules", I was trying to define the requirement
that "AlicesCalendar and BobsDocs are special, in a way that
monolog/monolog and google/apiclient are not".
--
Rowan Tommins
[IMSoP]