Container dependency injection in laravel, generating class instances multiple times

look at laravel in Comtroller to find that during class dependency injection, when I created an object through make , I found that multiple instances of the dependency were created.

the code is as follows:

<?php

namespace Tests\Unit;

use Illuminate\Container\Container;
use Tests\TestCase;

interface SessionStorage
{
    public function get($key);

    public function set($key, $value);
}

class FileSessionStorage implements SessionStorage
{
    public function __construct()
    {
        echo "file init \n";
    }

    public function get($key)
    {
        // TODO: Implement get() method.
    }

    public function set($key, $value)
    {
        // TODO: Implement set() method.
    }
}

class MySqlSessionStorage implements SessionStorage
{
    public function __construct()
    {
        echo "mysql init \n";
    }

    public function get($key)
    {
        // TODO: Implement get() method.
    }

    public function set($key, $value)
    {
        // TODO: Implement set() method.

    }
}

class SimpleAuth
{
    protected $session;

    public function __construct(SessionStorage $session)
    {
        $this->session = $session;
    }

    public function get()
    {
        $this->session->get(null);
    }

}

class ExampleTest extends TestCase
{
    /**
     * A basic test example.
     *
     * @return void
     */
    public function testBasicTest()
    {
        $container = Container::getInstance();

        $container->bind( SessionStorage::class, MysqlSessionStorage::class );
        $container->make(SimpleAuth::class);
        echo "-\n";

        $container->bind( SessionStorage::class, FileSessionStorage::class );
        $container->make(SimpleAuth::class);
        echo "-\n";

        $container->bind( SessionStorage::class, MysqlSessionStorage::class );
        $container->make(SimpleAuth::class);
    }
}
The output of the

code is as follows:

different than expected:

  1. the first make operation, you can see from the output of the constructor that the dependency is instantiated only once
  2. but then call bind , make found that the constructor was called twice
mysql init 
-
file init 
file init 
-
mysql init 
mysql init 

try debug : record the number of calls in the make function. :

public function make($abstract, array $parameters = [])
{
    if (stripos($abstract, "SessionStorage") !== false) {
        echo "make plus \n";
    }
    return $this->resolve($abstract, $parameters);
}

===================  =================
make plus 
make plus 
mysql init 
-
make plus 
make plus 
file init 
make plus 
make plus 
file init 
-
make plus 
make plus 
mysql init 
make plus 
make plus 
mysql init 

how to break!

Php
Mar.01,2021

follow the source code to find the problem:
1. When bind () is called, the abstract of bind will be placed in the bindings array;
2, when make () is called, if the call to resolve, is a singleton (singleton), it will be in instances. If it is returned, it is not a singleton, so there will be only one constructor call for each call.
3. But why is it called many times? the problem is that in the second bind (), because the make () has been passed before (that is, resolve), the rebound () function is called at the end of the bind () function, and a callback that abstract is used to call rebound is instantiated in the rebound () function.
4. So, instead of calling two instantiations on the second make (), it is the second bind () and the second make (), because the second bind triggers rebound;

.

(PS: doesn't know why I keep failing to upload pictures. Just look at the text)


binding method is bound to have multiple instances. Change bind to singleton bind

Menu