8000 [DependencyInjection] Allow for synthetic services before compilation by ro0NL · Pull Request #19619 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[DependencyInjection] Allow for synthetic services before compilation #19619

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 0 commits into from
Closed

[DependencyInjection] Allow for synthetic services before compilation #19619

wants to merge 0 commits into from

Conversation

ro0NL
Copy link
Contributor
@ro0NL ro0NL commented Aug 15, 2016
Q A
Branch? "master"
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets comma-separated list of tickets fixed by the PR, if any
License MIT
Doc PR reference to the documentation PR, if any

Separated from #19606

This allows accessing synthetic services from ContainerBuilder::get before compilation, besides they are exposed while extension loading.

It covers 2 usecases;

  • synthetic service + synthetic definition (like before, but getting the service is allowed)
  • synthetic service + non-synthetic definition (new feature => ServiceAwareDefinition which covers both usecases as well)

@@ -52,6 +52,10 @@ public function process(ContainerBuilder $container)
$tmpContainer->addExpressionLanguageProvider($provider);
}

foreach ($container->getSynthetics() as $id => $service) {
$tmpContainer->set($id, $service);
Copy link
Contributor Author
@ro0NL ro0NL Aug 15, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concerning BC: all services set via PrependExtensionInterface::prepend are now available while extension loading. Or any other service available at this point.

The services set while loading are not merged back into the container, this is perhaps considerable.

@GuilhemN
Copy link
Contributor

@ro0NL as #19608 is merged, I guess you can close this one ? :)

@ogizanagi
Copy link
Contributor
ogizanagi commented Aug 16, 2016

@Ener-Getick : My PR was only removing "dead code". It doesn't un-deprecate getting a service instance from the ContainerBuilder.

But I'm not convinced we need something like the new ServiceAwareDefinition. We could simply consider any service set using ContainerBuilder::set should be a "building-time only" service and allow to get it, but won't be available after compilation. It feels weird and I'm not convinced by this "feature" neither, but currently services set directly in the ContainerBuilder are vanished after compilation anyway.

@ro0NL
Copy link
Contributor Author
ro0NL commented Aug 16, 2016

Most important is the logic of ContainerBuider::get + MergeExtensionConfigurationPass::process for now.

ServiceAwareDefinition is somewhat a shortcut for set() + setDefinition(), so this can be left out yes. Consider it a poc :)

edit: @Ener-Getick i can rebase.. :)

@ro0NL
Copy link
Contributor Author
ro0NL commented Aug 16, 2016

@ogizanagi the ServiceAwareDefinition allows for having the service+definition at the same time, as set() overwrites definitions for the same id.

So if you have a non-synthetic definition + the ready to use service, you are stuck now. Not sure how common that is, on the other hand #19606 is poc of exactly that.

@ogizanagi
Copy link
Contributor
ogizanagi commented Aug 16, 2016

@ro0NL : My point is that you probably don't need having a service definition for services designed to be used during the container building time only (but is it even a good idea to depend on any kind of service in this phase ?). :/
I think that's the only thing needed for the use-case of exposing kernel & bundles "metadata".
Otherwise, either you'll get a service definition into the compiled container that will never be used at runtime, either you'll have to set the service twice (during and after the container is compiled).

Thus my suggestion about exposing a booting_kernel during the container build, which would simply be a KernelInterface decorator throwing an exception for unsafe methods, and will never be available at runtime (use the kernel service then). ^^

EDIT:

So if you have a non-synthetic definition + the ready to use service, you are stuck now. Not sure how common that is

As you said, not sure there are real use cases for this. Why would you need a container to build a service you're able to build yourself and would not be used at runtime ? Eventually you only need a way to share things during compilation time.
I think we're probably going in the wrong direction. The ContainerBuilder should probably not behaves as a Container. Maybe the ContainerBuilder is only missing a shared context somehow (immutable or locked at some point preferably. It's not safe to rely on if things can be put in at different building phases such as in the extension loading).

@ro0NL
Copy link
Contributor Author
ro0NL commented Aug 16, 2016

Could be.. this is just a generic approach that allows for it. If the component really needs it, i dont know. Perhaps nice to have. But yeah, my usecase is definitely kernel+bundles ;-)

A booting_kernel service will also do 👍

@ogizanagi
Copy link
Contributor
ogizanagi commented Aug 16, 2016

@ro0NL : regarding the part I've added after editing my comment above, here is a naive & straightforward implementation of a contextualized container builder, allowing to share some context during the build time, before compilation of the container: master...ogizanagi:contextualized_container

Here, the Context is locked right before calling Compiler::compile, ensuring nothing can mutate it appart from the Kernel::getContainerBuilder() method (actually, Kernel::registerContainerConfiguration() and BundleInterface::boot() can too). But we can imagine (if legit) locking the context only after some point (in a dedicated compiler pass), making the context mutable at some point (extensions) but "safe to use" only in compiler passes (which is where people tended to rely wrongly on services before the container was build before the ContainerBuilder::get() method was deprecated).

Of course, I don't expect this to be a perfect nor legit implementation, but simply exploring and giving more hints on how to proceed considering your uses cases. :)

@ro0NL
Copy link
Contributor Author
ro0NL commented Aug 16, 2016

@ogizanagi im thinking this thru.. maybe you're right on how we try to solve this and not being the right direction. It feels workaroundish i guess.

The ContainerBuilder should probably not behaves as a Container

  • Makes sense. Period. (before/while compilation that is)
  • How does this reflect ContainerBuilder::set? Should it even be allowed then?

I was also heading "context" way, and just had a crazy idea: ContainerBuilder::getContext():Container.

@ogizanagi
Copy link
Contributor
ogizanagi commented Aug 16, 2016

How does this reflect ContainerBuilder::set? Should it even be allowed then?

Indeed, it should not. I guess it was part of the idea behind the get deprecation, but it still allows to set synthetic services, which are vanished after compilation, and moreover not merged during build phase. So it may not allow calling set at all.

ContainerBuilder::getContext():Container

Yeah...thought about that too, but I'm not fan of giving visibility to the fact we use a container to build a container... 😅 At least the foolish lockable Context implementation hides that fact a little.

@ro0NL
Copy link
Contributor Author
ro0NL commented Aug 16, 2016

I dont mind :) I think we're too much used to one container being the almighty thing. It's a pattern, eventually it's legit 😉

Another, bridge too far, idea; each bundle defines it's own container(s) in the ecosystem. Container as a service 😱

Anyway, maybe focus this PR on deprecating set() first then? So at least the current behavior is consistent and clear.

@ogizanagi
8000 Copy link
Contributor

Anyway, maybe focus this PR on deprecating set() first then? So at least the current behavior is consistent and clear.

IMHO it should be the subject of another PR deprecating the whole set usage.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants
0