Shared object are not shared when extra parameters used #3192

Closed
skolodyazhnyy opened this Issue Dec 10, 2012 · 2 comments

Projects

None yet

2 participants

@skolodyazhnyy
Contributor

Hi,

I got this situation today, when I have created few class and tried to use Zend/Di for manage it instances.

Class definition:

class A {
    protected $name;
    public function __construct(G $g, $aName = "") {
        $this->name = $aName;
    }
}

class B {
    protected $name;
    public function __construct(G $g, $bName = "") {
        $this->name = $bName;
    }
}

class G {
    public function __construct() {
        echo "An instance created!";
    }
}

$config = array(
    'instance' => array(
        'G' => array('shared' => true)
    )
);

$di = new Zend\Di\Di();
$di->configure(new Zend\Di\Config($config));

Example A, works as I expect:

$di->get("A");
$di->get("B");
$di->get("G");

Output: "An instance created!", once

Example B, works really unexpected for me:

$di->get("A", array('aName' => 1));
$di->get("B", array('bName' => 2));
$di->get("G");

Output: "An instance created!", 3 times!

It's clear, if aName or bName parameters used by G, but it's not.

@skolodyazhnyy
Contributor

It's not a candidate to be a best fix, but it helps for me

diff --git a/lib/Zend/Di/Di.php b/lib/Zend/Di/Di.php
index 13c797a..f5e763f 100644
--- a/lib/Zend/Di/Di.php
+++ b/lib/Zend/Di/Di.php
@@ -119,6 +119,20 @@ class Di implements DependencyInjectionInterface
         return $this->instanceManager;
     }

+    public function _getCallParameters($name, array $params = array()) {
+        $im = $this->instanceManager;
+        $callParameters = array();
+        list($class, $alias) = ($im->hasAlias($name)) ? array($im->getClassFromAlias($name), $name) : array($name, null);
+        if($this->definitions->hasClass($class)) {
+            if ($this->definitions->hasMethod($class, '__construct')) {
+                foreach($this->definitions->getMethodParameters($class, '__construct') as $param)
+                    if(isset($params[$param[0]]))
+                        $callParameters[$param[0]] = $params[$param[0]];
+            }
+        }
+        return $callParameters;
+    }
+
     /**
      * Lazy-load a class
      *
@@ -136,18 +150,21 @@ class Di implements DependencyInjectionInterface

         $im = $this->instanceManager;

-        if ($params) {
-            $fastHash = $im->hasSharedInstanceWithParameters($name, $params, true);
+        // Shared objects params hash fix
+        $callParameters = $this->_getCallParameters($name, $params);
+
+        if ($callParameters) {
+            $fastHash = $im->hasSharedInstanceWithParameters($name, $callParameters, true);
             if ($fastHash) {
                 array_pop($this->instanceContext);

                 return $im->getSharedInstanceWithParameters(null, array(), $fastHash);
             }
         } else {
-            if ($im->hasSharedInstance($name, $params)) {
+            if ($im->hasSharedInstance($name, $callParameters)) {
                 array_pop($this->instanceContext);

-                return $im->getSharedInstance($name, $params);
+                return $im->getSharedInstance($name, $callParameters);
             }
         }
         $config = $im->getConfig($name);
@@ -226,8 +243,9 @@ class Di implements DependencyInjectionInterface
         }

         if ($isShared) {
-            if ($params) {
-                $this->instanceManager->addSharedInstanceWithParameters($instance, $name, $params);
+            // Shared objects params hash fix
+            if ($callParameters = $this->_getCallParameters($name, $params)) {
+                $this->instanceManager->addSharedInstanceWithParameters($instance, $name, $callParameters);
@weierophinney
Member

Closed with #3260

@gianarb gianarb pushed a commit to zendframework/zend-di that referenced this issue May 15, 2015
Sergey Kolodyazhnyy Di fix, retriving same shared instance for different extra parameters, 274cece
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment