On Sat, Mar 23, 2024, at 12:55 PM, Rasmus Schultz wrote: > Yes, this is very similar to the code in my second post - and yes, no > problem for basic factories like these to work in both compiled and > run-time containers. > > For extensions, it gets more challenging - a callback based container > doesn't have models and can't generate them from functions. > > In a nutshell, compiled containers are "data in, code out" - while > run-time containers, in relation to data-based service providers, would > be "have code, need data". > > Parsing code would be the only way to get from functions to models, but > that isn't going to make any sense in the context of e.g. Pimple.
(Please stop top posting. :-) ) To make sure we mean the same thing, what do you mean by "Extensions"? I'm imagining something like Symfony Compiler Passes where you can add "call this method after the object is created" commands and such, which, honestly, would be trivial to implement as PSR-14. (That kind of pattern was an explicit design goal.) You are correct that there's no meaningful way to turn $container->factory(Foo::class, fn(ContainerInterface $c) => new FooBar($c->get(Baz::class))); into an AST, so that isn't something a unified mechanism could support. I think where we disagree is whether that's fatal or not. I really don't think it is, not when any reasonably performant container already doesn't support that, because it's compiled anyway. (Something simple like Pimple is still pretty fast at read time, but has the overhead of re-registration on every request that slows it down.) But if a Provider returned an array like this: class Provider { public function getServices() { return [ Baz::class => new Service(Baz::class), FooBar::class => new Service(FooBar::class, [new DefRef(Baz::class)], ]; } } That would be quite easy for Pimple-like containers to support, and map back into a runtime model: public function registerProvider(Provider $provider) { foreach ($provider->getServices() as $name => $def) { $this->factories[$name] = static fn(ContainerInterface $c) => new ($def->class)($def->args); // OK, that line would be slightly more complicated for the arg handling, but you get the idea. } } And then its get() method looks exactly like it does today already. No issue. The *only* thing that is unsupportable in the standard itself would be class Provider { public function getServices() { return [ Foo::class => fn(ContainerInterface $c) => new FooBar($c->get(Baz::class))), ]; } } Which I am completely OK with not supporting, for the flexibility that gets us. Even without mentioning compilation, it wouldn't allow for other providers to modify the arguments; they could only add post-creation method calls. An AST approach would still allow a runtime container to have "alter hooks" if it wanted. --Larry Garfield -- You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group. To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/php-fig/f6c8db16-a5d4-4dee-95b9-85e56a9c4fa3%40app.fastmail.com.