Error: Container entry ... extends entry ... which is not an object #300

Closed
nstory opened this Issue Aug 19, 2015 · 2 comments

Comments

Projects
None yet
2 participants
@nstory

nstory commented Aug 19, 2015

<?php
require __DIR__ . '/vendor/autoload.php';

class A {}

$builder = new DI\ContainerBuilder;
$builder->addDefinitions([
    'A' => DI\factory(function() {
        return new A;
    }),
    'A2' => DI\object('A')
]);
$c = $builder->build();
$c->get('A2');

Results in the following error:

PHP Fatal error:  Uncaught exception 'DI\Definition\Exception\DefinitionException' with message 'Container entry 'A2' extends entry 'A' which is not an object' in /Users/nstory/src/php-di-whut/vendor/php-di/php-di/src/DI/Definition/ObjectDefinition.php:218
Stack trace:
#0 /Users/nstory/src/php-di-whut/vendor/php-di/php-di/src/DI/Definition/Source/SourceChain.php(98): DI\Definition\ObjectDefinition->setSubDefinition(Object(DI\Definition\FactoryDefinition))
#1 /Users/nstory/src/php-di-whut/vendor/php-di/php-di/src/DI/Definition/Source/SourceChain.php(62): DI\Definition\Source\SourceChain->resolveSubDefinition(Object(DI\Definition\ObjectDefinition), 1)
#2 /Users/nstory/src/php-di-whut/vendor/php-di/php-di/src/DI/Container.php(124): DI\Definition\Source\SourceChain->getDefinition('A2')
#3 /Users/nstory/src/php-di-whut/test.php(14): DI\Container->get('A2')
#4 {main}
  thrown in /Users/nstory/src/php-di-whut/vendor/php-di/php-di/src/DI/Definition/ObjectDefinition.php on line 218

Fatal error: Uncaught exception 'DI\Definition\Exception\DefinitionException' with message 'Container entry 'A2' extends entry 'A' which is not an object' in /Users/nstory/src/php-di-whut/vendor/php-di/php-di/src/DI/Definition/ObjectDefinition.php on line 218

DI\Definition\Exception\DefinitionException: Container entry 'A2' extends entry 'A' which is not an object in /Users/nstory/src/php-di-whut/vendor/php-di/php-di/src/DI/Definition/ObjectDefinition.php on line 218

Call Stack:
    0.0026     230288   1. {main}() /Users/nstory/src/php-di-whut/test.php:0
    0.0071     564760   2. DI\Container->get() /Users/nstory/src/php-di-whut/test.php:14
    0.0071     564864   3. DI\Definition\Source\SourceChain->getDefinition() /Users/nstory/src/php-di-whut/vendor/php-di/php-di/src/DI/Container.php:124
    0.0077     618304   4. DI\Definition\Source\SourceChain->resolveSubDefinition() /Users/nstory/src/php-di-whut/vendor/php-di/php-di/src/DI/Definition/Source/SourceChain.php:62
    0.0079     626264   5. DI\Definition\ObjectDefinition->setSubDefinition() /Users/nstory/src/php-di-whut/vendor/php-di/php-di/src/DI/Definition/Source/SourceChain.php:98

My expected behavior is for there to have been no error, and for two definitions to exist, each mapping to a separate instance of the class A.

Notes:

  • Removing the definition for A or changing that definition to 'A' => DI\object() eliminates the error.
  • This only occurs in PHP-DI v5+, I am not seeing this error in v4.4.10
@mnapoli

This comment has been minimized.

Show comment
Hide comment
@mnapoli

mnapoli Aug 25, 2015

Member

Hi, thanks for the detailed report, and sorry for the delay (I saw the notification but then forgot about it :/).

What you described is somewhat an intended behavior but at the same time it's quite confusing.

To explain why it happens: DI\object('X') means indirectly "extend the previous definition X". That's meant primarily for extending autowiring definitions. But this behavior has confusing side effects, e.g. the one you describe or what's discussed in #294.

We have 2 solutions here:

  • don't throw the exception, just don't extend a definition that isn't an object
  • find a more global solution so that DI\object() has a less surprising behavior (for example users would have to call something explicitly if they want to extend the previous definition… that's just an idea)

The second solution is a big task, maybe the first task can be done as a quick fix.

Member

mnapoli commented Aug 25, 2015

Hi, thanks for the detailed report, and sorry for the delay (I saw the notification but then forgot about it :/).

What you described is somewhat an intended behavior but at the same time it's quite confusing.

To explain why it happens: DI\object('X') means indirectly "extend the previous definition X". That's meant primarily for extending autowiring definitions. But this behavior has confusing side effects, e.g. the one you describe or what's discussed in #294.

We have 2 solutions here:

  • don't throw the exception, just don't extend a definition that isn't an object
  • find a more global solution so that DI\object() has a less surprising behavior (for example users would have to call something explicitly if they want to extend the previous definition… that's just an idea)

The second solution is a big task, maybe the first task can be done as a quick fix.

mnapoli added a commit that referenced this issue Aug 25, 2015

Fix #300 If an object definition "extends" an incompatible definitio…
…n, ignore it instead of throwing an exception
@mnapoli

This comment has been minimized.

Show comment
Hide comment
@mnapoli

mnapoli Aug 25, 2015

Member

I have opened #302 with the quick-fix solution.

This however doesn't solve this:

[
    'A' => DI\object()->constructor('Hello),
    'A2' => DI\object('A')
]

In this example A2 will have inherited the ->constructor('Hello) from A, which is a feature but can be confusing.

Member

mnapoli commented Aug 25, 2015

I have opened #302 with the quick-fix solution.

This however doesn't solve this:

[
    'A' => DI\object()->constructor('Hello),
    'A2' => DI\object('A')
]

In this example A2 will have inherited the ->constructor('Hello) from A, which is a feature but can be confusing.

@mnapoli mnapoli added the bug label Aug 25, 2015

@mnapoli mnapoli added this to the 5.1 milestone Aug 25, 2015

@mnapoli mnapoli closed this in #302 Sep 1, 2015

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