John Smith
John Smith

Reputation: 6197

Php, DI, references doesnt work as expected

a simple example:

class A
{
    /**
     * @var Injected
     */
    private $injected;

    public function __construct(Injected $injected)
    {
        $this->injected = $injected;
    }

    public function get()
    {
        $this->injected->e();
    }
}

class B
{
    /**
     * @var Injected
     */
    private $injected;

    public function __construct(Injected $injected)
    {
        $this->injected = $injected;
    }

    public function get()
    {
        $this->injected->e();
    }
}

class Injected
{
    private $a;
    public function __construct()
    {
        $this->a = mt_rand(1,9999999999);
        echo 'Generated: '.$this->a.'<br>';
    }
    public function e()
    {
        echo $this->a.'<br>';
    }
}

$o = new Injected();
$a = new A($o);
$b = new B($o);
$a->get();
$b->get();
$o = new Injected();
$a->get();
$b->get();

and when I run:

Generated: 1223710791
1223710791
1223710791
Generated: 1135116298
1223710791
1223710791

its not precisely what I expected. The first three 1223710791 is correct - but the last two seems to be failed. I wanted to get this!

Generated: 1223710791
1223710791
1223710791
Generated: 1135116298
1135116298
1135116298

it looks like even I replace the reference of $o it wont change in the A and B classes. Why? If they were normal variables, it would be understandable, but they are object and so references! I didnt even cloned them... that way there is no way to change $injected, apart from setters (which not an option this time)

Upvotes: 0

Views: 45

Answers (2)

Federkun
Federkun

Reputation: 36954

You can have that (strange, and potentially unpredictable) behavior by replacing the constructor of your A/B classes:

public function __construct(Injected &$injected)
{
    $this->injected = &$injected;
}

Upvotes: 2

Robert
Robert

Reputation: 10390

You can use PHP's static features for this. You could say they work almost like references, I don't know all the details under the hood but the following will work as you expected.

You need to change some of Injected's code to static and leave the others untouched:

class A
{
    /**
     * @var Injected
     */
    private $injected;

    public function __construct(Injected $injected)
    {
        $this->injected = $injected;
    }

    public function get()
    {
        $this->injected->e();
    }
}

class B
{
    /**
     * @var Injected
     */
    private $injected;

    public function __construct(Injected $injected)
    {
        $this->injected = $injected;
    }

    public function get()
    {
        $this->injected->e();
    }
}

class Injected
{
    private static $a;
    public function __construct()
    {
        self::$a = mt_rand(1,9999999999);
        echo 'Generated: '.self::$a.'<br>';
    }
    public function e()
    {
        echo self::$a.'<br>';
    }
}

$o = new Injected();
$a = new A($o);
$b = new B($o);
$a->get();
$b->get();
$o = new Injected();
$a->get();
$b->get();

Result:

Generated: 5231916164
5231916164
5231916164
Generated: 166525017
166525017
166525017

Upvotes: 0

Related Questions