On 28 June 2026 09:49:51 BST, Alexander Egorov <[email protected]> wrote:
>In my vision, the primary use of containers would be through supplying
>proper autoloaders for them. In this case, all code inside the container
>and which relies by default on autoloading (which is the majority of cases)
>will load all classes in a way we expect with corresponding tags. And so we
>would be able to easily match all classes.
OK, then your vision is fundamentally different from mine. I don't want the
container to know *anything* about how the code inside it works.
Remember that autoloading is something that any library can implement its own
version of. There are autoloaders which fetch from PHAR files, autoloaders
which generate code on demand, and so on.
Version tags break the abstraction of the container, and I don't think they
solve a real problem.
>Your case differs from that because, as I understand it, it loads classes
>manually depending on the conditions.
No, just that the container configuration doesn't know anything about
"packages" or "versions". You run 'require "$someDir/vendor/autoload.php";'
inside the container as normal. Or maybe you don't, and you just list a big
bunch of includes for some reason. The container doesn't care.
As a human author, you maybe know what versions of packages are in your
container - depending how tightly you've configured them - but you have no idea
what someone *else* might include in their container.
If you include version 2.11 of Monolog and version 2.0 of psr/log, but some
other container includes version 2.11 of Monolog and version 3.0 of psr/log,
those objects aren't interchangeable. If you treat them as though they are,
something is going to blow up in your face.
>$client2 = $container->run(fn() => new \Google\Client);
>$logger2 = $client2->getLogger();
>
>match (true) {
> $logger2 instanceof Logger => ...., // here I mean less formal instanceof
> $logger2 instanceof LoggerV1 => ...,
> $logger2 instanceof LoggerV2 => ...,
>}
I think you're still missing the point - if I pass around $client2, and it
passes checks for "instanceof Google\Client", I can pass it to functions which
have no idea it came from a different container. They will have no idea that it
might return an object from getLogger() which doesn't pass a check for
"instanceof Logger".
>In my vision, "tag" does not really identify the container. It is whatever
>we wish semantically. For example, let's say we're using Monolog\Logger 2.0
>as our "default" logger. But we also use another library which is designed
>for 1.0. And for us that Logger from version 1.0 would be identified as
>("1.0", Logger) according to the semantics we've chosen and which is
>reflected in our autoloader.
I think the only way for two containers to agree that a class is the same, is
if they both start with that class name already defined, so it points to the
same class entry in memory.
Otherwise, containers can completely break each other by using the same tags
for different definitions.
>But speaking about the example you provided with google
>client, it is a good example why such "polymorphic" libraries themselves
>would benefit from such class-versioning and containerization and would
>themselves want to switch to it to get rid of all that compatibility
>shenanigans.
On the contrary, the entire point of packages like psr/log is to define objects
which can be passed around from one package to another. By advertising that it
can be installed with multiple versions of something, a library is giving
applications freedom to resolve a set of versions which works for them.
That's exactly why I've been arguing for a distinction between "modules" and
"containers", and saying that the vast majority of current code would not
benefit from containers at all.
Rowan Tommins
[IMSoP]