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]

Reply via email to