Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

[DependencyInjection] call synchronize{$id} from get{$id}Service method #8545

Closed
wants to merge 5 commits into from

3 participants

@jaypea

this calls the synchronize method for services that are marked as synchronized but are not synthetic.

when the scope of the requested service is not active, the container won't create the instance nor call the synchronize method.
when the scope gets entered and the service is fetched from container afterwards, the synchronize{$id}Service method is called to update all dependent services.

Jan Prieser call synchronize{$id} from get{$id}Service method
this calls the synchronize method for services that are marked as synchronized but are not synthetic.
when the scope of the requested service is not active, the container won't create the instance nor call the synchronize method.
when the scope gets entered and the service is injected afterwards, the synchronize{$id}Service method is called to update all dependent services.
e8930fa
@stof
Collaborator

Please test this

Jan Prieser added some commits
@jaypea

the tests fail with a segmentation fault for php 5.3.3. its running in the other versions jobs.
but this has nothing to do with my code, the master branch is failing since yesterday: https://travis-ci.org/symfony/symfony/builds

...ny/Component/DependencyInjection/Dumper/PhpDumper.php
@@ -420,6 +420,18 @@ private function addServiceProperties($id, $definition, $variableName = 'instanc
return $code;
}
+ private function addServiceSynchronizeCall($id, $definition)
@stof Collaborator
stof added a note

could you typehint the Definition ?

@jaypea
jaypea added a note

there are lots of similar methods in this class without typehints.
if was thinking about it, but decided to stick with the convention in the class.

@stof Collaborator
stof added a note

I think typehinting the object arguments is better (and SensioLabs Insight agrees with me as it checks for it). So I think the new code should use the typehint (changing the existing code is probably outside the scope of this PR).

@fabpot Owner
fabpot added a note

Type hinting is indeed a good idea.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
...nt/DependencyInjection/Tests/Dumper/PhpDumperTest.php
@@ -181,4 +182,20 @@ public function testOverrideServiceWhenUsingADumpedContainerAndServiceIsUsedFrom
$this->assertSame($bar, $container->get('foo')->bar, '->set() overrides an already defined service');
}
+
+ public function testSynchronizedServiceUpdatesDependencies() {
@stof Collaborator
stof added a note

the curly brace should be on its own line

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
...nt/DependencyInjection/Tests/Dumper/PhpDumperTest.php
@@ -11,6 +11,7 @@
namespace Symfony\Component\DependencyInjection\Tests\Dumper;
+use Symfony\Component\DependencyInjection\Container;
@stof Collaborator
stof added a note

is it used ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
...cyInjection/Tests/Fixtures/containers/container15.php
((3 lines not shown))
+require_once __DIR__.'/../includes/classes.php';
+
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\Parameter;
+
+$container = new ContainerBuilder();
+$container->addScope(new \Symfony\Component\DependencyInjection\Scope('request'));
+$container
+ ->register('synchronizedService', 'BarClass')
+ ->setSynchronized(true)
+ ->setScope('request')
+;
+$container
+ ->register('dependsOnSynchronized', 'FooClass')
@stof Collaborator
stof added a note

Please use underscored names instead of camel cased names to follow the DIC conventions (camelCase does nto really make sense for case insensitive ids)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@fabpot fabpot commented on the diff
...cyInjection/Tests/Fixtures/containers/container15.php
((1 lines not shown))
+<?php
+
+require_once __DIR__.'/../includes/classes.php';
+
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\Parameter;
+
+$container = new ContainerBuilder();
+$container->addScope(new \Symfony\Component\DependencyInjection\Scope('request'));
+$container
+ ->register('synchronized_service', 'BarClass')
+ ->setSynchronized(true)
+ ->setScope('request')
+;
@fabpot Owner
fabpot added a note

If a service is synchronized, it should not be in the request scope. A service should be either in the request scope or synchrnonized, not both.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@fabpot
Owner

Closing this one as there is no feedback and because there is a better way in Symfony 2.4 with the request stack service.

@fabpot fabpot closed this
@jaypea jaypea deleted the jaypea:synchronize branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jul 23, 2013
  1. call synchronize{$id} from get{$id}Service method

    Jan Prieser authored
    this calls the synchronize method for services that are marked as synchronized but are not synthetic.
    when the scope of the requested service is not active, the container won't create the instance nor call the synchronize method.
    when the scope gets entered and the service is injected afterwards, the synchronize{$id}Service method is called to update all dependent services.
  2. fix output

    Jan Prieser authored
  3. adds unit test for synchronizing services

    Jan Prieser authored
  4. fix code review findings

    Jan Prieser authored
This page is out of date. Refresh to see the latest.
View
15 src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
@@ -378,7 +378,7 @@ private function isSimpleInstance($id, $definition)
continue;
}
- if ($sDefinition->getMethodCalls() || $sDefinition->getProperties() || $sDefinition->getConfigurator()) {
+ if ($sDefinition->getMethodCalls() || $sDefinition->getProperties() || $sDefinition->getConfigurator() || $sDefinition->isSynchronized()) {
return false;
}
}
@@ -420,6 +420,18 @@ private function addServiceProperties($id, $definition, $variableName = 'instanc
return $code;
}
+ private function addServiceSynchronizeCall($id, Definition $definition)
+ {
+ if (!$definition->isSynchronized()) {
+ return '';
+ }
+
+ $name = 'synchronize'.$this->camelize($id).'Service';
+ $code = sprintf(" \$this->%s();\n", $name);
+
+ return $code;
+ }
+
/**
* Generates the inline definition setup.
*
@@ -585,6 +597,7 @@ private function addService($id, $definition)
$this->addServiceMethodCalls($id, $definition).
$this->addServiceProperties($id, $definition).
$this->addServiceConfigurator($id, $definition).
+ $this->addServiceSynchronizeCall($id, $definition).
$this->addServiceReturn($id, $definition)
;
}
View
17 src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php
@@ -181,4 +181,21 @@ public function testOverrideServiceWhenUsingADumpedContainerAndServiceIsUsedFrom
$this->assertSame($bar, $container->get('foo')->bar, '->set() overrides an already defined service');
}
+
+ public function testSynchronizedServiceUpdatesDependencies()
+ {
+ require_once self::$fixturesPath.'/includes/foo.php';
+ require_once self::$fixturesPath.'/includes/classes.php';
+ require_once self::$fixturesPath.'/php/services15.php';
+
+ $container = new \AnotherProjectServiceContainer();
+ $dependentService = $container->get('depends_on_synchronized');
+ $this->assertNull($dependentService->bar);
+
+ $container->enterScope('request');
+ $synchronizedService = $container->get('synchronized_service');
+
+ $this->assertEquals($dependentService->bar, $synchronizedService);
+
+ }
}
View
22 src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container15.php
@@ -0,0 +1,22 @@
+<?php
+
+require_once __DIR__.'/../includes/classes.php';
+
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\Parameter;
+
+$container = new ContainerBuilder();
+$container->addScope(new \Symfony\Component\DependencyInjection\Scope('request'));
+$container
+ ->register('synchronized_service', 'BarClass')
+ ->setSynchronized(true)
+ ->setScope('request')
+;
@fabpot Owner
fabpot added a note

If a service is synchronized, it should not be in the request scope. A service should be either in the request scope or synchrnonized, not both.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+$container
+ ->register('depends_on_synchronized', 'FooClass')
+ ->addMethodCall('setBar', array(new Reference('synchronized_service', ContainerInterface::NULL_ON_INVALID_REFERENCE, false)))
+;
+
+return $container;
View
91 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services15.php
@@ -0,0 +1,91 @@
+<?php
+
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\DependencyInjection\Container;
+use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+use Symfony\Component\DependencyInjection\Exception\LogicException;
+use Symfony\Component\DependencyInjection\Exception\RuntimeException;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\Parameter;
+use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
+
+/**
+ * AnotherProjectServiceContainer
+ *
+ * This class has been auto-generated
+ * by the Symfony Dependency Injection Component.
+ */
+class AnotherProjectServiceContainer extends Container
+{
+ /**
+ * Constructor.
+ */
+ public function __construct()
+ {
+ $this->services =
+ $this->scopedServices =
+ $this->scopeStacks = array();
+
+ $this->set('service_container', $this);
+
+ $this->scopes = array('request' => 'container');
+ $this->scopeChildren = array('request' => array());
+ $this->methodMap = array(
+ 'depends_on_synchronized' => 'getDependsonsynchronizedService',
+ 'synchronized_service' => 'getSynchronizedserviceService',
+ );
+
+ $this->aliases = array();
+ }
+
+ /**
+ * Gets the 'dependsonsynchronized' service.
+ *
+ * This service is shared.
+ * This method always returns the same instance of the service.
+ *
+ * @return FooClass A FooClass instance.
+ */
+ protected function getDependsonsynchronizedService()
+ {
+ $this->services['depends_on_synchronized'] = $instance = new \FooClass();
+
+ $instance->setBar($this->get('synchronized_service', ContainerInterface::NULL_ON_INVALID_REFERENCE));
+
+ return $instance;
+ }
+
+ /**
+ * Gets the 'synchronizedservice' service.
+ *
+ * This service is shared.
+ * This method always returns the same instance of the service.
+ *
+ * @return BarClass A BarClass instance.
+ *
+ * @throws InactiveScopeException when the 'synchronizedservice' service is requested while the 'request' scope is not active
+ */
+ protected function getSynchronizedserviceService()
+ {
+ if (!isset($this->scopedServices['request'])) {
+ throw new InactiveScopeException('synchronized_service', 'request');
+ }
+
+ $this->services['synchronized_service'] = $this->scopedServices['request']['synchronized_service'] = $instance = new \BarClass();
+
+ $this->synchronizeSynchronizedserviceService();
+
+ return $instance;
+ }
+
+ /**
+ * Updates the 'synchronizedservice' service.
+ */
+ protected function synchronizeSynchronizedserviceService()
+ {
+ if ($this->initialized('depends_on_synchronized')) {
+ $this->get('depends_on_synchronized')->setBar($this->get('synchronized_service', ContainerInterface::NULL_ON_INVALID_REFERENCE));
+ }
+ }
+}
Something went wrong with that request. Please try again.