[DI] Add ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE

This commit is contained in:
Nicolas Grekas 2017-08-30 09:27:55 +02:00
parent 80ac529742
commit 0db3358ddb
26 changed files with 431 additions and 53 deletions

View File

@ -4,6 +4,7 @@ CHANGELOG
3.4.0
-----
* added support for ignore-on-uninitialized references
* deprecated service auto-registration while autowiring
* deprecated the ability to check for the initialization of a private service with the `Container::initialized()` method
* deprecated support for top-level anonymous services in XML

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\ExpressionLanguage;
use Symfony\Component\DependencyInjection\Reference;
@ -96,7 +97,8 @@ class AnalyzeServiceReferencesPass extends AbstractRecursivePass implements Repe
$this->getDefinitionId((string) $value),
$targetDefinition,
$value,
$this->lazy || ($targetDefinition && $targetDefinition->isLazy())
$this->lazy || ($targetDefinition && $targetDefinition->isLazy()),
ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior()
);
return $value;

View File

@ -11,6 +11,7 @@
namespace Symfony\Component\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Reference;
@ -24,14 +25,16 @@ class CheckExceptionOnInvalidReferenceBehaviorPass extends AbstractRecursivePass
{
protected function processValue($value, $isRoot = false)
{
if ($value instanceof Reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $value->getInvalidBehavior()) {
$destId = (string) $value;
if (!$this->container->has($destId)) {
throw new ServiceNotFoundException($destId, $this->currentId);
}
if (!$value instanceof Reference) {
return parent::processValue($value, $isRoot);
}
if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $value->getInvalidBehavior() && !$this->container->has($id = (string) $value)) {
throw new ServiceNotFoundException($id, $this->currentId);
}
if (ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior() && $this->container->has($id = (string) $value) && !$this->container->findDefinition($id)->isShared()) {
throw new InvalidArgumentException(sprintf('Invalid ignore-on-uninitialized reference found in service "%s": target service "%s" is not shared.', $this->currentId, $id));
}
return parent::processValue($value, $isRoot);
return $value;
}
}

View File

@ -96,6 +96,9 @@ class InlineServiceDefinitionsPass extends AbstractRecursivePass implements Repe
$ids = array();
foreach ($graph->getNode($id)->getInEdges() as $edge) {
if ($edge->isWeak()) {
return false;
}
$ids[] = $edge->getSourceNode()->getId();
}

View File

@ -74,6 +74,9 @@ class RegisterServiceSubscribersPass extends AbstractRecursivePass
if ($optionalBehavior = '?' === $type[0]) {
$type = substr($type, 1);
$optionalBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
} elseif ($optionalBehavior = '!' === $type[0]) {
$type = substr($type, 1);
$optionalBehavior = ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE;
}
if (is_int($key)) {
$key = $type;

View File

@ -50,6 +50,9 @@ class RemoveUnusedDefinitionsPass implements RepeatablePassInterface
$referencingAliases = array();
$sourceIds = array();
foreach ($edges as $edge) {
if ($edge->isWeak()) {
continue;
}
$node = $edge->getSourceNode();
$sourceIds[] = $node->getId();

View File

@ -20,6 +20,8 @@ use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
* it themselves which improves performance quite a lot.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*
* @final since version 3.4
*/
class ServiceReferenceGraph
{
@ -85,23 +87,16 @@ class ServiceReferenceGraph
* @param string $destValue
* @param string $reference
* @param bool $lazy
* @param bool $weak
*/
public function connect($sourceId, $sourceValue, $destId, $destValue = null, $reference = null/*, bool $lazy = false*/)
public function connect($sourceId, $sourceValue, $destId, $destValue = null, $reference = null/*, bool $lazy = false, bool $weak = false*/)
{
if (func_num_args() >= 6) {
$lazy = func_get_arg(5);
} else {
if (__CLASS__ !== get_class($this)) {
$r = new \ReflectionMethod($this, __FUNCTION__);
if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
@trigger_error(sprintf('Method %s() will have a 6th `bool $lazy = false` argument in version 4.0. Not defining it is deprecated since 3.3.', __METHOD__), E_USER_DEPRECATED);
}
}
$lazy = false;
}
$lazy = func_num_args() >= 6 ? func_get_arg(5) : false;
$weak = func_num_args() >= 7 ? func_get_arg(6) : false;
$sourceNode = $this->createNode($sourceId, $sourceValue);
$destNode = $this->createNode($destId, $destValue);
$edge = new ServiceReferenceGraphEdge($sourceNode, $destNode, $reference, $lazy);
$edge = new ServiceReferenceGraphEdge($sourceNode, $destNode, $reference, $lazy, $weak);
$sourceNode->addOutEdge($edge);
$destNode->addInEdge($edge);

View File

@ -24,19 +24,22 @@ class ServiceReferenceGraphEdge
private $destNode;
private $value;
private $lazy;
private $weak;
/**
* @param ServiceReferenceGraphNode $sourceNode
* @param ServiceReferenceGraphNode $destNode
* @param string $value
* @param bool $lazy
* @param bool $weak
*/
public function __construct(ServiceReferenceGraphNode $sourceNode, ServiceReferenceGraphNode $destNode, $value = null, $lazy = false)
public function __construct(ServiceReferenceGraphNode $sourceNode, ServiceReferenceGraphNode $destNode, $value = null, $lazy = false, $weak = false)
{
$this->sourceNode = $sourceNode;
$this->destNode = $destNode;
$this->value = $value;
$this->lazy = $lazy;
$this->weak = $weak;
}
/**
@ -78,4 +81,14 @@ class ServiceReferenceGraphEdge
{
return $this->lazy;
}
/**
* Returns true if the edge is weak, meaning it shouldn't prevent removing the target service.
*
* @return bool
*/
public function isWeak()
{
return $this->weak;
}
}

View File

@ -23,26 +23,15 @@ use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
* Container is a dependency injection container.
*
* It gives access to object instances (services).
*
* Services and parameters are simple key/pair stores.
*
* Parameter and service keys are case insensitive.
*
* A service can also be defined by creating a method named
* getXXXService(), where XXX is the camelized version of the id:
*
* <ul>
* <li>request -> getRequestService()</li>
* <li>mysql_session_storage -> getMysqlSessionStorageService()</li>
* <li>symfony.mysql_session_storage -> getSymfony_MysqlSessionStorageService()</li>
* </ul>
*
* The container can have three possible behaviors when a service does not exist:
* The container can have four possible behaviors when a service
* does not exist (or is not initialized for the last case):
*
* * EXCEPTION_ON_INVALID_REFERENCE: Throws an exception (the default)
* * NULL_ON_INVALID_REFERENCE: Returns null
* * IGNORE_ON_INVALID_REFERENCE: Ignores the wrapping command asking for the reference
* (for instance, ignore a setter if the service does not exist)
* * IGNORE_ON_UNINITIALIZED_REFERENCE: Ignores/returns null for uninitialized services or invalid references
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
@ -304,9 +293,9 @@ class Container implements ResettableContainerInterface
try {
if (isset($this->fileMap[$id])) {
return $this->load($this->fileMap[$id]);
return self::IGNORE_ON_UNINITIALIZED_REFERENCE === $invalidBehavior ? null : $this->load($this->fileMap[$id]);
} elseif (isset($this->methodMap[$id])) {
return $this->{$this->methodMap[$id]}();
return self::IGNORE_ON_UNINITIALIZED_REFERENCE === $invalidBehavior ? null : $this->{$this->methodMap[$id]}();
} elseif (--$i && $id !== $normalizedId = $this->normalizeId($id)) {
$id = $normalizedId;
continue;
@ -315,7 +304,7 @@ class Container implements ResettableContainerInterface
// and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper)
@trigger_error('Generating a dumped container without populating the method map is deprecated since 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', E_USER_DEPRECATED);
return $this->{$method}();
return self::IGNORE_ON_UNINITIALIZED_REFERENCE === $invalidBehavior ? null : $this->{$method}();
}
break;

View File

@ -565,6 +565,9 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
{
$id = $this->normalizeId($id);
if (ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $invalidBehavior) {
return parent::get($id, $invalidBehavior);
}
if ($service = parent::get($id, ContainerInterface::NULL_ON_INVALID_REFERENCE)) {
return $service;
}
@ -1160,6 +1163,11 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
continue 2;
}
}
foreach (self::getInitializedConditionals($v) as $s) {
if (!$this->get($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)) {
continue 2;
}
}
yield $k => $this->resolveServices($v);
}
@ -1171,6 +1179,11 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
continue 2;
}
}
foreach (self::getInitializedConditionals($v) as $s) {
if (!$this->get($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)) {
continue 2;
}
}
++$count;
}
@ -1397,6 +1410,8 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
* @param mixed $value An array of conditionals to return
*
* @return array An array of Service conditionals
*
* @internal since version 3.4
*/
public static function getServiceConditionals($value)
{
@ -1413,6 +1428,30 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
return $services;
}
/**
* Returns the initialized conditionals.
*
* @param mixed $value An array of conditionals to return
*
* @return array An array of uninitialized conditionals
*
* @internal
*/
public static function getInitializedConditionals($value)
{
$services = array();
if (is_array($value)) {
foreach ($value as $v) {
$services = array_unique(array_merge($services, self::getInitializedConditionals($v)));
}
} elseif ($value instanceof Reference && $value->getInvalidBehavior() === ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE) {
$services[] = (string) $value;
}
return $services;
}
/**
* Computes a reasonably unique hash of a value.
*
@ -1465,13 +1504,16 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
private function callMethod($service, $call)
{
$services = self::getServiceConditionals($call[1]);
foreach ($services as $s) {
foreach (self::getServiceConditionals($call[1]) as $s) {
if (!$this->has($s)) {
return;
}
}
foreach (self::getInitializedConditionals($call[1]) as $s) {
if (!$this->get($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)) {
return;
}
}
call_user_func_array(array($service, $call[0]), $this->resolveServices($this->getParameterBag()->unescapeValue($this->getParameterBag()->resolveValue($call[1]))));
}

View File

@ -27,6 +27,7 @@ interface ContainerInterface extends PsrContainerInterface
const EXCEPTION_ON_INVALID_REFERENCE = 1;
const NULL_ON_INVALID_REFERENCE = 2;
const IGNORE_ON_INVALID_REFERENCE = 3;
const IGNORE_ON_UNINITIALIZED_REFERENCE = 4;
/**
* Sets a service.

View File

@ -277,7 +277,7 @@ EOF;
if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $behavior[$id]) {
$code .= sprintf($template, $name, $this->getServiceCall($id));
} else {
$code .= sprintf($template, $name, $this->getServiceCall($id, new Reference($id, ContainerInterface::NULL_ON_INVALID_REFERENCE)));
$code .= sprintf($template, $name, $this->getServiceCall($id, new Reference($id, $behavior[$id])));
}
}
}
@ -1295,12 +1295,14 @@ EOF;
*/
private function getServiceConditionals($value)
{
if (!$services = ContainerBuilder::getServiceConditionals($value)) {
return null;
}
$conditions = array();
foreach ($services as $service) {
foreach (ContainerBuilder::getInitializedConditionals($value) as $service) {
if (!$this->container->hasDefinition($service)) {
return 'false';
}
$conditions[] = sprintf("isset(\$this->services['%s'])", $service);
}
foreach (ContainerBuilder::getServiceConditionals($value) as $service) {
if ($this->container->hasDefinition($service) && !$this->container->getDefinition($service)->isPublic()) {
continue;
}
@ -1335,8 +1337,8 @@ EOF;
}
if (!isset($behavior[$id])) {
$behavior[$id] = $argument->getInvalidBehavior();
} elseif (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $behavior[$id]) {
$behavior[$id] = $argument->getInvalidBehavior();
} else {
$behavior[$id] = min($behavior[$id], $argument->getInvalidBehavior());
}
++$calls[$id];
@ -1665,7 +1667,9 @@ EOF;
return '$this';
}
if ($this->asFiles && $this->container->hasDefinition($id)) {
if (null !== $reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $reference->getInvalidBehavior()) {
$code = 'null';
} elseif ($this->asFiles && $this->container->hasDefinition($id)) {
if ($this->container->getDefinition($id)->isShared()) {
$code = sprintf("\$this->load(__DIR__.'/%s.php')", $this->generateMethodName($id));
} else {

View File

@ -309,6 +309,8 @@ class XmlDumper extends Dumper
$element->setAttribute('on-invalid', 'null');
} elseif ($behaviour == ContainerInterface::IGNORE_ON_INVALID_REFERENCE) {
$element->setAttribute('on-invalid', 'ignore');
} elseif ($behaviour == ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE) {
$element->setAttribute('on-invalid', 'ignore_uninitialized');
}
} elseif ($value instanceof Definition) {
$element->setAttribute('type', 'service');

View File

@ -304,8 +304,12 @@ class YamlDumper extends Dumper
*/
private function getServiceCall($id, Reference $reference = null)
{
if (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) {
return sprintf('@?%s', $id);
if (null !== $reference) {
switch ($reference->getInvalidBehavior()) {
case ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE: break;
case ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE: return sprintf('@!%s', $id);
default: return sprintf('@?%s', $id);
}
}
return sprintf('@%s', $id);

View File

@ -492,6 +492,8 @@ class XmlFileLoader extends FileLoader
$invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
if ('ignore' == $onInvalid) {
$invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
} elseif ('ignore_uninitialized' == $onInvalid) {
$invalidBehavior = ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE;
} elseif ('null' == $onInvalid) {
$invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE;
}

View File

@ -758,6 +758,9 @@ class YamlFileLoader extends FileLoader
if (0 === strpos($value, '@@')) {
$value = substr($value, 1);
$invalidBehavior = null;
} elseif (0 === strpos($value, '@!')) {
$value = substr($value, 2);
$invalidBehavior = ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE;
} elseif (0 === strpos($value, '@?')) {
$value = substr($value, 2);
$invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;

View File

@ -266,6 +266,7 @@
<xsd:enumeration value="null" />
<xsd:enumeration value="ignore" />
<xsd:enumeration value="exception" />
<xsd:enumeration value="ignore_uninitialized" />
</xsd:restriction>
</xsd:simpleType>

View File

@ -67,6 +67,27 @@ class CheckExceptionOnInvalidReferenceBehaviorPassTest extends TestCase
$this->process($container);
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessage Invalid ignore-on-uninitialized reference found in service
*/
public function testProcessThrowsExceptionOnNonSharedUninitializedReference()
{
$container = new ContainerBuilder();
$container
->register('a', 'stdClass')
->addArgument(new Reference('b', $container::IGNORE_ON_UNINITIALIZED_REFERENCE))
;
$container
->register('b', 'stdClass')
->setShared(false)
;
$this->process($container);
}
private function process(ContainerBuilder $container)
{
$pass = new CheckExceptionOnInvalidReferenceBehaviorPass();

View File

@ -1098,6 +1098,38 @@ class ContainerBuilderTest extends TestCase
$this->assertSame($container->get('bar_service'), $foo->get('bar'));
}
public function testUninitializedReference()
{
$container = include __DIR__.'/Fixtures/containers/container_uninitialized_ref.php';
$container->compile();
$bar = $container->get('bar');
$this->assertNull($bar->foo1);
$this->assertNull($bar->foo2);
$this->assertNull($bar->foo3);
$this->assertNull($bar->closures[0]());
$this->assertNull($bar->closures[1]());
$this->assertNull($bar->closures[2]());
$this->assertSame(array(), iterator_to_array($bar->iter));
$container = include __DIR__.'/Fixtures/containers/container_uninitialized_ref.php';
$container->compile();
$container->get('foo1');
$container->get('baz');
$bar = $container->get('bar');
$this->assertEquals(new \stdClass(), $bar->foo1);
$this->assertNull($bar->foo2);
$this->assertEquals(new \stdClass(), $bar->foo3);
$this->assertEquals(new \stdClass(), $bar->closures[0]());
$this->assertNull($bar->closures[1]());
$this->assertEquals(new \stdClass(), $bar->closures[2]());
$this->assertEquals(array('foo1' => new \stdClass(), 'foo3' => new \stdClass()), iterator_to_array($bar->iter));
}
public function testRegisterForAutoconfiguration()
{
$container = new ContainerBuilder();

View File

@ -631,6 +631,44 @@ class PhpDumperTest extends TestCase
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_private_in_expression.php', $dumper->dump());
}
public function testUninitializedReference()
{
$container = include self::$fixturesPath.'/containers/container_uninitialized_ref.php';
$container->compile();
$dumper = new PhpDumper($container);
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_uninitialized_ref.php', $dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Uninitialized_Reference')));
require self::$fixturesPath.'/php/services_uninitialized_ref.php';
$container = new \Symfony_DI_PhpDumper_Test_Uninitialized_Reference();
$bar = $container->get('bar');
$this->assertNull($bar->foo1);
$this->assertNull($bar->foo2);
$this->assertNull($bar->foo3);
$this->assertNull($bar->closures[0]());
$this->assertNull($bar->closures[1]());
$this->assertNull($bar->closures[2]());
$this->assertSame(array(), iterator_to_array($bar->iter));
$container = new \Symfony_DI_PhpDumper_Test_Uninitialized_Reference();
$container->get('foo1');
$container->get('baz');
$bar = $container->get('bar');
$this->assertEquals(new \stdClass(), $bar->foo1);
$this->assertNull($bar->foo2);
$this->assertEquals(new \stdClass(), $bar->foo3);
$this->assertEquals(new \stdClass(), $bar->closures[0]());
$this->assertNull($bar->closures[1]());
$this->assertEquals(new \stdClass(), $bar->closures[2]());
$this->assertEquals(array('foo1' => new \stdClass(), 'foo3' => new \stdClass()), iterator_to_array($bar->iter));
}
public function testDumpHandlesLiteralClassWithRootNamespace()
{
$container = new ContainerBuilder();

View File

@ -12,8 +12,12 @@
namespace Symfony\Component\DependencyInjection\Tests\Dumper;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Dumper\XmlDumper;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Reference;
class XmlDumperTest extends TestCase
{
@ -184,6 +188,18 @@ class XmlDumperTest extends TestCase
$this->assertEquals(file_get_contents(self::$fixturesPath.'/xml/services24.xml'), $dumper->dump());
}
public function testDumpLoad()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('services_dump_load.xml');
$this->assertEquals(array(new Reference('bar', ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)), $container->getDefinition('foo')->getArguments());
$dumper = new XmlDumper($container);
$this->assertStringEqualsFile(self::$fixturesPath.'/xml/services_dump_load.xml', $dumper->dump());
}
public function testDumpAbstractServices()
{
$container = include self::$fixturesPath.'/containers/container_abstract.php';

View File

@ -14,9 +14,11 @@ namespace Symfony\Component\DependencyInjection\Tests\Dumper;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Dumper\YamlDumper;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\Yaml\Yaml;
use Symfony\Component\Yaml\Parser;
@ -73,6 +75,8 @@ class YamlDumperTest extends TestCase
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('services_dump_load.yml');
$this->assertEquals(array(new Reference('bar', ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)), $container->getDefinition('foo')->getArguments());
$dumper = new YamlDumper($container);
$this->assertStringEqualsFile(self::$fixturesPath.'/yaml/services_dump_load.yml', $dumper->dump());
}

View File

@ -0,0 +1,46 @@
<?php
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
$container = new ContainerBuilder();
$container
->register('foo1', 'stdClass')
;
$container
->register('foo2', 'stdClass')
->setPublic(false)
;
$container
->register('foo3', 'stdClass')
->setPublic(false)
;
$container
->register('baz', 'stdClass')
->setProperty('foo3', new Reference('foo3'))
;
$container
->register('bar', 'stdClass')
->setProperty('foo1', new Reference('foo1', $container::IGNORE_ON_UNINITIALIZED_REFERENCE))
->setProperty('foo2', new Reference('foo2', $container::IGNORE_ON_UNINITIALIZED_REFERENCE))
->setProperty('foo3', new Reference('foo3', $container::IGNORE_ON_UNINITIALIZED_REFERENCE))
->setProperty('closures', array(
new ServiceClosureArgument(new Reference('foo1', $container::IGNORE_ON_UNINITIALIZED_REFERENCE)),
new ServiceClosureArgument(new Reference('foo2', $container::IGNORE_ON_UNINITIALIZED_REFERENCE)),
new ServiceClosureArgument(new Reference('foo3', $container::IGNORE_ON_UNINITIALIZED_REFERENCE)),
))
->setProperty('iter', new IteratorArgument(array(
'foo1' => new Reference('foo1', $container::IGNORE_ON_UNINITIALIZED_REFERENCE),
'foo2' => new Reference('foo2', $container::IGNORE_ON_UNINITIALIZED_REFERENCE),
'foo3' => new Reference('foo3', $container::IGNORE_ON_UNINITIALIZED_REFERENCE),
)))
;
return $container;

View File

@ -0,0 +1,138 @@
<?php
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
/**
* Symfony_DI_PhpDumper_Test_Uninitialized_Reference.
*
* This class has been auto-generated
* by the Symfony Dependency Injection Component.
*
* @final since Symfony 3.3
*/
class Symfony_DI_PhpDumper_Test_Uninitialized_Reference extends Container
{
private $parameters;
private $targetDirs = array();
/**
* Constructor.
*/
public function __construct()
{
$this->services = array();
$this->methodMap = array(
'bar' => 'getBarService',
'baz' => 'getBazService',
'foo1' => 'getFoo1Service',
'foo3' => 'getFoo3Service',
);
$this->privates = array(
'foo3' => true,
);
$this->aliases = array();
}
/**
* {@inheritdoc}
*/
public function compile()
{
throw new LogicException('You cannot compile a dumped container that was already compiled.');
}
/**
* {@inheritdoc}
*/
public function isCompiled()
{
return true;
}
/**
* {@inheritdoc}
*/
public function isFrozen()
{
@trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED);
return true;
}
/**
* Gets the public 'bar' shared service.
*
* @return \stdClass
*/
protected function getBarService()
{
$this->services['bar'] = $instance = new \stdClass();
$instance->foo1 = ${($_ = isset($this->services['foo1']) ? $this->services['foo1'] : null) && false ?: '_'};
$instance->foo2 = null;
$instance->foo3 = ${($_ = isset($this->services['foo3']) ? $this->services['foo3'] : null) && false ?: '_'};
$instance->closures = array(0 => function () {
return ${($_ = isset($this->services['foo1']) ? $this->services['foo1'] : null) && false ?: '_'};
}, 1 => function () {
return null;
}, 2 => function () {
return ${($_ = isset($this->services['foo3']) ? $this->services['foo3'] : null) && false ?: '_'};
});
$instance->iter = new RewindableGenerator(function () {
if (isset($this->services['foo1'])) {
yield 'foo1' => ${($_ = isset($this->services['foo1']) ? $this->services['foo1'] : null) && false ?: '_'};
}
if (false) {
yield 'foo2' => null;
}
if (isset($this->services['foo3'])) {
yield 'foo3' => ${($_ = isset($this->services['foo3']) ? $this->services['foo3'] : null) && false ?: '_'};
}
}, function () {
return 0 + (int) (isset($this->services['foo1'])) + (int) (false) + (int) (isset($this->services['foo3']));
});
return $instance;
}
/**
* Gets the public 'baz' shared service.
*
* @return \stdClass
*/
protected function getBazService()
{
$this->services['baz'] = $instance = new \stdClass();
$instance->foo3 = ${($_ = isset($this->services['foo3']) ? $this->services['foo3'] : $this->getFoo3Service()) && false ?: '_'};
return $instance;
}
/**
* Gets the public 'foo1' shared service.
*
* @return \stdClass
*/
protected function getFoo1Service()
{
return $this->services['foo1'] = new \stdClass();
}
/**
* Gets the private 'foo3' shared service.
*
* @return \stdClass
*/
protected function getFoo3Service()
{
return $this->services['foo3'] = new \stdClass();
}
}

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="service_container" class="Symfony\Component\DependencyInjection\ContainerInterface" synthetic="true"/>
<service id="foo" autoconfigure="true" abstract="true">
<argument type="service" id="bar" on-invalid="ignore_uninitialized"/>
</service>
<service id="Psr\Container\ContainerInterface" alias="service_container" public="false"/>
<service id="Symfony\Component\DependencyInjection\ContainerInterface" alias="service_container" public="false"/>
</services>
</container>

View File

@ -6,6 +6,7 @@ services:
foo:
autoconfigure: true
abstract: true
arguments: ['@!bar']
Psr\Container\ContainerInterface:
alias: service_container
public: false