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.
  • Service Provi... Rasmus Schultz
    • Re: Serv... Larry Garfield
      • Re: ... Rasmus Schultz
      • Re: ... Rasmus Schultz
        • ... Larry Garfield
          • ... Rasmus Schultz
            • ... Larry Garfield
              • ... Rasmus Schultz
                • ... Larry Garfield
                • ... Rasmus Schultz
                • ... Steve McDougall
                • ... Rasmus Schultz
                • ... Larry Garfield
                • ... Chuck Burgess
                • ... Rasmus Schultz
                • ... Ken Guest
                • ... 'Alexander Makarov' via PHP Framework Interoperability Group
                • ... Cees-Jan Kiewiet
                • ... Rasmus Schultz

Reply via email to