merged branch ludekstepan/fix-di-scope-nesting (PR #6119)

This PR was submitted for the master branch but it was merged into the 2.1 branch instead (closes #6119).

Commits
-------

3b9f763 [DI] Fix 'undefined index' error, when entering scope recursively

Discussion
----------

[DI] Fix 'undefined index' error, when entering scope recursively

Imagine two scopes:

```php
$container = new Container();
$container->addScope(new Scope('foo'));
$container->addScope(new Scope('bar', 'foo'));
```

Enter the same scope twice recursively:

```php
$container->enterScope('foo');
// not entering bar in between
$container->enterScope('foo');
// prints warning: undefined index: bar
// at Symfony/Component/DependencyInjection/Container.php:341
```

---------------------------------------------------------------------------

by fabpot at 2012-11-28T16:30:00Z

The problem exists, but the fix looks wrong to me. We should keep the scoped services even with nested scopes. Right now, and even after your patch, we loose some information.

---------------------------------------------------------------------------

by ludekstepan at 2012-11-28T16:38:05Z

I don't know how to fix properly, the patch above is just a workaround.

Without the patch, it's not possible to simply create a child scope of the "request" scope, because "enterScope" would fail upon every forward between "request" and nested "request" unless "bar" scope was entered prior to forward.

---------------------------------------------------------------------------

by stof at 2012-11-28T16:51:50Z

@fabpot why would it be wrong ? If the nested scope was not active when entering a subrequest, there is simply nothing to save

---------------------------------------------------------------------------

by stloyd at 2013-01-04T18:16:54Z

Any news about this one ? =)

---------------------------------------------------------------------------

by stof at 2013-01-04T18:22:58Z

@fabpot could you explain which info we are loosing ?
This commit is contained in:
Fabien Potencier 2013-02-07 23:17:35 +01:00
commit 0c63bbdb01
2 changed files with 36 additions and 2 deletions

View File

@ -334,8 +334,10 @@ class Container implements IntrospectableContainerInterface
unset($this->scopedServices[$name]);
foreach ($this->scopeChildren[$name] as $child) {
$services[$child] = $this->scopedServices[$child];
unset($this->scopedServices[$child]);
if (isset($this->scopedServices[$child])) {
$services[$child] = $this->scopedServices[$child];
unset($this->scopedServices[$child]);
}
}
// update global map

View File

@ -261,6 +261,38 @@ class ContainerTest extends \PHPUnit_Framework_TestCase
$this->assertFalse($container->has('a'));
}
public function testEnterScopeRecursivelyWithInactiveChildScopes()
{
$container = new Container();
$container->addScope(new Scope('foo'));
$container->addScope(new Scope('bar', 'foo'));
$this->assertFalse($container->isScopeActive('foo'));
$container->enterScope('foo');
$this->assertTrue($container->isScopeActive('foo'));
$this->assertFalse($container->isScopeActive('bar'));
$this->assertFalse($container->has('a'));
$a = new \stdClass();
$container->set('a', $a, 'foo');
$services = $this->getField($container, 'scopedServices');
$this->assertTrue(isset($services['foo']['a']));
$this->assertSame($a, $services['foo']['a']);
$this->assertTrue($container->has('a'));
$container->enterScope('foo');
$services = $this->getField($container, 'scopedServices');
$this->assertFalse(isset($services['a']));
$this->assertTrue($container->isScopeActive('foo'));
$this->assertFalse($container->isScopeActive('bar'));
$this->assertFalse($container->has('a'));
}
public function testLeaveScopeNotActive()
{
$container = new Container();