feature #9791 [DependencyInjection] added support for inlining Configurators (realityking)

This PR was merged into the 2.5-dev branch.

Discussion
----------

[DependencyInjection] added support for inlining Configurators

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | -
| License       | MIT
| Doc PR        | -

This is one commit from #9432.

As mentioned in #3758 configurators can not be private (it's just ignored). This pull changes that and allows them to be inlined. It it also creates better code if a configurator is used multiple times for one service (i.e. to both inject it and configure the same service, or to configure multiple inlined services) but this should be very rare.

Commits
-------

4e9aa07 [DependencyInjection] added support for inlining Configurators
This commit is contained in:
Fabien Potencier 2013-12-16 19:58:20 +01:00
commit c0a7e1b6e5
8 changed files with 109 additions and 7 deletions

View File

@ -62,6 +62,11 @@ class InlineServiceDefinitionsPass implements RepeatablePassInterface
$definition->setProperties(
$this->inlineArguments($container, $definition->getProperties())
);
$configurator = $this->inlineArguments($container, array($definition->getConfigurator()));
$definition->setConfigurator(
$configurator[0]
);
}
}

View File

@ -159,6 +159,7 @@ class PhpDumper extends Dumper
$this->getServiceCallsFromArguments($iDefinition->getArguments(), $calls, $behavior);
$this->getServiceCallsFromArguments($iDefinition->getMethodCalls(), $calls, $behavior);
$this->getServiceCallsFromArguments($iDefinition->getProperties(), $calls, $behavior);
$this->getServiceCallsFromArguments(array($iDefinition->getConfigurator()), $calls, $behavior);
}
$code = '';
@ -481,8 +482,9 @@ class PhpDumper extends Dumper
}
if (is_array($callable)) {
if ($callable[0] instanceof Reference) {
return sprintf(" %s->%s(\$%s);\n", $this->getServiceCall((string) $callable[0]), $callable[1], $variableName);
if ($callable[0] instanceof Reference
|| ($callable[0] instanceof Definition && $this->definitionVariables->contains($callable[0]))) {
return sprintf(" %s->%s(\$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName);
}
return sprintf(" call_user_func(array(%s, '%s'), \$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName);
@ -1070,7 +1072,8 @@ EOF;
$definitions = array_merge(
$this->getDefinitionsFromArguments($definition->getArguments()),
$this->getDefinitionsFromArguments($definition->getMethodCalls()),
$this->getDefinitionsFromArguments($definition->getProperties())
$this->getDefinitionsFromArguments($definition->getProperties()),
$this->getDefinitionsFromArguments(array($definition->getConfigurator()))
);
$this->inlinedDefinitions->offsetSet($definition, $definitions);

View File

@ -83,5 +83,14 @@ $container
->register('depends_on_request', 'stdClass')
->addMethodCall('setRequest', array(new Reference('request', ContainerInterface::NULL_ON_INVALID_REFERENCE, false)))
;
$container
->register('configurator_service', 'ConfClass')
->setPublic(false)
->addMethodCall('setFoo', array(new Reference('baz')))
;
$container
->register('configured_service', 'stdClass')
->setConfigurator(array(new Reference('configurator_service'), 'configureStdClass'))
;
return $container;

View File

@ -14,6 +14,8 @@ digraph sc {
node_baz [label="baz\nBaz\n", shape=record, fillcolor="#eeeeee", style="filled"];
node_request [label="request\nRequest\n", shape=record, fillcolor="#eeeeee", style="filled"];
node_depends_on_request [label="depends_on_request\nstdClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
node_configurator_service [label="configurator_service\nConfClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
node_configured_service [label="configured_service\nstdClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
node_service_container [label="service_container\nSymfony\\Component\\DependencyInjection\\ContainerBuilder\n", shape=record, fillcolor="#9999ff", style="filled"];
node_foo2 [label="foo2\n\n", shape=record, fillcolor="#ff9999", style="filled"];
node_foo3 [label="foo3\n\n", shape=record, fillcolor="#ff9999", style="filled"];
@ -31,4 +33,5 @@ digraph sc {
node_inlined -> node_baz [label="setBaz()" style="dashed"];
node_baz -> node_foo_with_inline [label="setFoo()" style="dashed"];
node_depends_on_request -> node_request [label="setRequest()" style="dashed"];
node_configurator_service -> node_baz [label="setFoo()" style="dashed"];
}

View File

@ -25,6 +25,8 @@ class ProjectServiceContainer extends Container
$this->methodMap = array(
'bar' => 'getBarService',
'baz' => 'getBazService',
'configurator_service' => 'getConfiguratorServiceService',
'configured_service' => 'getConfiguredServiceService',
'depends_on_request' => 'getDependsOnRequestService',
'factory_service' => 'getFactoryServiceService',
'foo' => 'getFooService',
@ -51,9 +53,11 @@ class ProjectServiceContainer extends Container
*/
protected function getBarService()
{
$this->services['bar'] = $instance = new \FooClass('foo', $this->get('foo.baz'), $this->getParameter('foo_bar'));
$a = $this->get('foo.baz');
$this->get('foo.baz')->configure($instance);
$this->services['bar'] = $instance = new \FooClass('foo', $a, $this->getParameter('foo_bar'));
$a->configure($instance);
return $instance;
}
@ -75,6 +79,23 @@ class ProjectServiceContainer extends Container
return $instance;
}
/**
* Gets the 'configured_service' service.
*
* This service is shared.
* This method always returns the same instance of the service.
*
* @return stdClass A stdClass instance.
*/
protected function getConfiguredServiceService()
{
$this->services['configured_service'] = $instance = new \stdClass();
$this->get('configurator_service')->configureStdClass($instance);
return $instance;
}
/**
* Gets the 'depends_on_request' service.
*
@ -224,6 +245,27 @@ class ProjectServiceContainer extends Container
}
}
/**
* Gets the 'configurator_service' service.
*
* This service is shared.
* This method always returns the same instance of the service.
*
* This service is private.
* If you want to be able to request this service from the container directly,
* make it public, otherwise you might end up with broken code.
*
* @return ConfClass A ConfClass instance.
*/
protected function getConfiguratorServiceService()
{
$this->services['configurator_service'] = $instance = new \ConfClass();
$instance->setFoo($this->get('baz'));
return $instance;
}
/**
* Gets the 'inlined' service.
*

View File

@ -34,6 +34,7 @@ class ProjectServiceContainer extends Container
$this->methodMap = array(
'bar' => 'getBarService',
'baz' => 'getBazService',
'configured_service' => 'getConfiguredServiceService',
'depends_on_request' => 'getDependsOnRequestService',
'factory_service' => 'getFactoryServiceService',
'foo' => 'getFooService',
@ -59,9 +60,11 @@ class ProjectServiceContainer extends Container
*/
protected function getBarService()
{
$this->services['bar'] = $instance = new \FooClass('foo', $this->get('foo.baz'), $this->getParameter('foo_bar'));
$a = $this->get('foo.baz');
$this->get('foo.baz')->configure($instance);
$this->services['bar'] = $instance = new \FooClass('foo', $a, $this->getParameter('foo_bar'));
$a->configure($instance);
return $instance;
}
@ -83,6 +86,26 @@ class ProjectServiceContainer extends Container
return $instance;
}
/**
* Gets the 'configured_service' service.
*
* This service is shared.
* This method always returns the same instance of the service.
*
* @return stdClass A stdClass instance.
*/
protected function getConfiguredServiceService()
{
$a = new \ConfClass();
$a->setFoo($this->get('baz'));
$this->services['configured_service'] = $instance = new \stdClass();
$a->configureStdClass($instance);
return $instance;
}
/**
* Gets the 'depends_on_request' service.
*

View File

@ -76,6 +76,14 @@
<argument type="service" id="request" on-invalid="null" strict="false"/>
</call>
</service>
<service id="configurator_service" class="ConfClass" public="false">
<call method="setFoo">
<argument type="service" id="baz"/>
</call>
</service>
<service id="configured_service" class="stdClass">
<configurator service="configurator_service" method="configureStdClass"/>
</service>
<service id="alias_for_foo" alias="foo"/>
<service id="alias_for_alias" alias="foo"/>
</services>

View File

@ -70,5 +70,14 @@ services:
calls:
- [setRequest, ['@?request']]
configurator_service:
class: ConfClass
public: false
calls:
- [setFoo, ['@baz']]
configured_service:
class: stdClass
configurator: ['@configurator_service', configureStdClass]
alias_for_foo: @foo
alias_for_alias: @foo