Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[DI][RFC] Container scripts #22365

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
backbone87 opened this issue Apr 10, 2017 · 7 comments
Closed

[DI][RFC] Container scripts #22365

backbone87 opened this issue Apr 10, 2017 · 7 comments

Comments

@backbone87
Copy link
Contributor

Q A
Bug report? no
Feature request? yes
BC Break report? no
RFC? yes

In #21837 there was basically a hack used to add some load time code to the container.

Besides that the service configuration defined in the different config files is heavily altered by extensions/configurators/compiler passes so you need to consult a different sources scattered around various places: Resources/config, *Bundle.php (for compiler passes actually used), *Extension.php (dynamic config), *Pass.php (for container building code) and some more depending on how sophisticated your feature's DI integration is.

The container:debug commands helps only to some degree, to at least get a view of the final result, but still gives no clue about where to look for the configuration of a specific service.

To consolidate these various sources, I propose something like "container-scripts". An example how #21837 could be solved with it:

<container ... >
  <services>
    <service id="annotations.reader" class="Doctrine\Common\Annotations\AnnotationReader" public="false">
      ...
    </service>
  <services>
  <factory-script type="php/closure" depends="annotations.reader" on-missing="skip"><![CDATA[
    Doctrine\Common\Annotations\AnnotationRegistry::registerLoader('class_exists');
  ]]></factory-script>
</container>

This would execute the script each time the service "annotations.reader" is initialized/created ("newed").

Script scenarios:

  • <config-script> script executed during configuration, maybe to include config resources depending on the env; would be executed right after the config resource is loaded (before following config resources are loaded)
  • <build-script> like extensions
  • <compile-script> like compiler passes
  • <load-script> executed when the container is loaded/booted
  • <factory-script> executed when services are "newed"

WDYT

@sstok
Copy link
Contributor

sstok commented Apr 11, 2017

Note that the Container needs to be able to work without compiling down to a PHP file first, and eval is only limitedly possible. And adding to much extensions for the dumping process could lead to some hart debug situations and BC promises (as some will expect access to service variables $a).

You can already solve the configuration of a service after creation using a Configurator.
http://symfony.com/doc/current/service_container/configurators.html

Allowing to register CompilerPasses (classes only) in services.{xml,yml} file would be a good enhancement. But the PHP version of services.php files already support this (as it receives the ContainerBuilder) so I'm not if its use-case is good enough to support this in other formats as well 🤔

@backbone87
Copy link
Contributor Author

what about load time scripts and/or factory scripts? a use case came up exactly with annotation loader PR

container build code pushed down into config files could solve the problem (maybe its just my problem) of scattered container build resources

but using php as config file format is actually a good idea. some tools of the node.js environment use config files written in js, which has some beauty to it. but this still doesnt solve scripts ran during container "execution"

@stof
Copy link
Member

stof commented Apr 11, 2017

-1 for putting code in the config files to be evaled (because this is what you are asking).

If you want to have some code running at the instantiation time (your factory-script), you can (ab)use the service configurator for that (which allows to call a function to complete the service instantiation).

For your build-time logic, use extensions or compiler passes instead of trying to hide things inside services and asking us to eval it.
And for the load-script, we don't want people to be able to run arbitrary logic easily at this point, as it would impact performance. And in the case of the Symfony framework, you can use the boot method of the bundle to hook there (though the recommendation is to be careful with it due to performance impact).

@sstok
Copy link
Contributor

sstok commented Apr 11, 2017

but this still doesnt solve scripts ran during container "execution"

You can use a http://symfony.com/doc/current/service_container/configurators.html but it does mean your configuration is separate.

If you want to have some code running at the instantiation time (your factory-script), you can (ab)use the service configurator for that (which allows to call a function to complete the service instantiation).

Indeed.

@nicolas-grekas
Copy link
Member

-1 also. Yes #21837 is a hack. But we have already everything at hand to turn it into a non-hack if we wanted to do so: just create a factory or a configurator and implement the logic there.
We don't need "eval" variants as @stof explained.

@backbone87
Copy link
Contributor Author

didnt know about configurators before -- yes they solve the "factory-script" case
and boot methods can solve the "load-script" case

it still feels cumbersome to search in many different places (and often in 300+ LoC Extension classes) to find the piece of code responsible to build/configure a specific service/group of services.

@nicolas-grekas
Copy link
Member

Closing as explained.

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

No branches or pull requests

5 participants