Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Add check to DI to see if we have a class to instantiate #4790

Closed
wants to merge 4 commits into from

3 participants

@nickpeirson

Currently the DI container throws a fatal error when trying to instantiate a class that doesn't exist or, more usually, when DI tries to instantiate an interface.

The fatal error looks like:

PHP Fatal error:  Cannot instantiate interface Foo\Bar in /Users/nickpeirson/projects/mycg/vendor/zendframework/zend-di/Zend/Di/Di.php on line 452

This PR changes the behaviour to check for the existence of the of the class before trying to instantiate it and throws and exception accordingly. This results in a much more developer friendly backtrace allowing a developer to identify the problem more quickly and spend less time debugging. As we see this most commonly when we've missed a type preference for an interface I've also added a case for when the class to be instantiated is in fact an interface, to add clarity to the thrown exception.

@nickpeirson nickpeirson Add checks to see if we have a class to instantiate
Also added a special case for when we're mistakenly trying to instantiate an interface
57eeb78
@samsonasik

please provide unit test.

@nickpeirson

Add a unit test that covers the exception being thrown. Working through it it seems like the underlying problem could be with the definition produced by Zend\Di\Definition\CompilerDefinition, as I can't reproduce it just using the runtime definition.

That being said, with the current state of the definition compiler this is a problem (I don't have time right now to dig into the compiler, but I may come back to it in the future), however this mitigates it so I feel it's worth adding.

tests/ZendTest/Di/TestAsset/ConstructorInjection/D.php
@@ -0,0 +1,22 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+*
+* @link http://github.com/zendframework/zf2 for the canonical source repository
+* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
+* @license http://framework.zend.com/license/new-bsd New BSD License
+* @package Zend_Di

remove @package

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
tests/ZendTest/Di/TestAsset/DummyInterface.php
@@ -0,0 +1,16 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @package Zend_Di

remove @package

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@weierophinney weierophinney referenced this pull request from a commit
@weierophinney weierophinney [#4790] CS fixes
- Use sprint for exception message string interpolation
- No need for escaping namespace separators when class names are
  uppercase
4007247
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jul 5, 2013
  1. @nickpeirson

    Add checks to see if we have a class to instantiate

    nickpeirson authored
    Also added a special case for when we're mistakenly trying to instantiate an interface
Commits on Jul 15, 2013
  1. @nickpeirson
  2. @nickpeirson

    Tidy up CS violations

    nickpeirson authored
  3. @nickpeirson
This page is out of date. Refresh to see the latest.
View
7 library/Zend/Di/Di.php
@@ -446,6 +446,13 @@ protected function createInstanceViaConstructor($class, $params, $alias = null)
$callParameters = $this->resolveMethodParameters($class, '__construct', $params, $alias, self::METHOD_IS_CONSTRUCTOR, true);
}
+ if (!class_exists($class)) {
+ if (interface_exists($class)) {
+ throw new Exception\ClassNotFoundException('Cannot instantiate interface '.$class);
+ }
+ throw new Exception\ClassNotFoundException($class.' does not exist');
+ }
+
// Hack to avoid Reflection in most common use cases
switch (count($callParameters)) {
case 0:
View
35 tests/ZendTest/Di/DiTest.php
@@ -474,6 +474,41 @@ public function testNewInstanceWillUsePreferredClassForInterfaceHints()
$this->assertSame($a, $d->a);
}
+ public function testNewInstanceWillThrowAnClassNotFoundExceptionWhenClassIsAnInterface()
+ {
+ $definitionArray = array (
+ 'ZendTest\\Di\\TestAsset\\ConstructorInjection\\D' => array(
+ 'supertypes' => array(),
+ 'instantiator' => '__construct',
+ 'methods' => array('__construct' => 3),
+ 'parameters' => array(
+ '__construct' =>
+ array (
+ 'ZendTest\\Di\\TestAsset\\ConstructorInjection\\D::__construct:0' => array(
+ 0 => 'd',
+ 1 => 'ZendTest\\Di\\TestAsset\\DummyInterface',
+ 2 => true,
+ 3 => NULL,
+ ),
+ ),
+ ),
+ ),
+ 'ZendTest\\Di\\TestAsset\\DummyInterface' => array(
+ 'supertypes' => array(),
+ 'instantiator' => NULL,
+ 'methods' => array(),
+ 'parameters' => array(),
+ ),
+ );
+ $definitionList = new DefinitionList(array(
+ new Definition\ArrayDefinition($definitionArray)
+ ));
+ $di = new Di($definitionList);
+
+ $this->setExpectedException('Zend\Di\Exception\ClassNotFoundException', 'Cannot instantiate interface');
+ $di->get('ZendTest\Di\TestAsset\ConstructorInjection\D');
+ }
+
public function testMatchPreferredClassWithAwareInterface()
{
$di = new Di();
View
21 tests/ZendTest/Di/TestAsset/ConstructorInjection/D.php
@@ -0,0 +1,21 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+*
+* @link http://github.com/zendframework/zf2 for the canonical source repository
+* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
+* @license http://framework.zend.com/license/new-bsd New BSD License
+*/
+
+namespace ZendTest\Di\TestAsset\ConstructorInjection;
+
+use ZendTest\Di\TestAsset\DummyInterface;
+
+class D
+{
+ protected $d = null;
+ public function __construct(DummyInterface $d)
+ {
+ $this->d = $d;
+ }
+}
View
15 tests/ZendTest/Di/TestAsset/DummyInterface.php
@@ -0,0 +1,15 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+namespace ZendTest\Di\TestAsset;
+
+interface DummyInterface
+{
+ public function __construct();
+}
Something went wrong with that request. Please try again.