Three realms of PHP decoupling (service container)

Keywords: Session PHP Database

First realm

Suppose the scenario: We need to write a processing class that can operate on sessions, databases, and file systems at the same time.We might write that.
Realm characteristics: can run, but severely coupled

<?php
/**
 * First
 */
namespace test1;

class DB{
    public function __construct($arg1,$arg2){
        echo 'constructed'.PHP_EOL;
    }
}

class FileSystem{
    public function __construct($arg1,$arg2){
        echo 'constructed'.PHP_EOL;
    }
}

class Session{
    public function __construct($arg1,$arg2) {
        echo 'constructed'.PHP_EOL;
    }
}

class Writer{
    public function __construct()
    {
        $db=new DB(1,2);
        $filesystem=new FileSystem(3,4);
        $session=new Session(5,6);
    }
}

$writer=new Writer();

Writing drawbacks:
1. Constructing objects in public functions can take a lot of work to modify once changes such as database parameters are involved
2. People responsible for designing Writer classes need to be familiar with the various API s for classes such as DB
Is there any way to reduce coupling?

Second realm (parameter dependency)

Suppose the scenario: Database addresses need to be changed frequently because of different customers, and there are many (if there are dozens) of classes called to DB that you don't need to modify the code of even if you change the database address.

<?php
/**
 * Second
 */
namespace test2;

class DB{
    public function __construct($arg1,$arg2){
        echo 'constructed'.PHP_EOL;
    }
}

class FileSystem{
    public function __construct($arg1,$arg2){
        echo 'constructed'.PHP_EOL;
    }
}

class Session{
    public function __construct($arg1,$arg2) {
        echo 'constructed'.PHP_EOL;
    }
}

class Writer{
    protected $_db;
    protected $_filesystem;
    protected $_session;
    public function Set($db,$filesystem,$session){
        $this->_db=$db;
        $this->_filesystem=$filesystem;
        $this->_session=$session;
    }
}

$db=new DB(1,2);
$filesystem=new FileSystem(3,4);
$session=new Session(5,6);
$writer=new Writer();
$writer->Set($db,$filesystem,$session);

Although the construction of DB classes has been moved to the client side, once modifications have been involved, the workload has been greatly reduced. In order to create a Writer class, we need to create the DB class, FileSystem class, etc. first. This is very demanding for the person responsible for the Writer class, he needs to see many other class documents, oneCreate (and possibly initialize) before creating the writer variable he wants.

So we want a better way of writing so that people who write Writer classes can create and call the classes they want with a faster interface, even without filling in the parameters.

Third realm (IOC container)

After the first two levels, we hope to add the following benefits:

  1. You want the DB class, Session class, and FileSystem class to "take and use" without having to write every tedious initialization, such as $db=new DB(arg1,arg2); such statements.
  2. You want objects of type DB to be "global" and be callable at any time during the entire program run.
  3. Programmers who call types such as DB don't need to know too much about this class, and can even create such an object with a string alias.

To accomplish this, the IOC container is simply a global variable that binds strings to constructors using an associated array.

<?php
/**
 * Third
 */
namespace test3;

class DB{
    public function __construct($arg1,$arg2){
        echo 'constructed'.PHP_EOL;
    }
}

class FileSystem{
    public function __construct($arg1,$arg2){
        echo 'constructed'.PHP_EOL;
    }
}

class Session{
    public function __construct($arg1,$arg2) {
        echo 'constructed'.PHP_EOL;
    }
}

class Container{
    public $bindings;
    public function bind($abstract,$concrete){
        $this->bindings[$abstract]=$concrete;
    }
    public function make($abstract,$parameters=[]){
        return call_user_func_array($this->bindings[$abstract],$parameters);
    }
}

$container=new Container();
$container->bind('db',function ($arg1,$arg2){return new DB($arg1,$arg2);});
$container->bind('filesystem',function ($arg1,$arg2){return new FileSystem($arg1,$arg2);});
$container->bind('session',function ($arg1,$arg2){return new Session($arg1,$arg2);});

class Writer{
    protected $_db;
    protected $_filesystem;
    protected $_session;
    protected $container;
    public function __construct(Container $container)
    {
        $this->_db=$container->make('db',[1,2]);
        $this->_filesystem=$container->make('filesystem',[3,4]);
        $this->_session=$container->make('session',[5,6]);
    }
}

$writer=new Writer($container);

Posted by The_broken on Tue, 09 Jul 2019 10:48:20 -0700