Автор оригинала: David Wong.
Я видел много фреймворков раньше, laravel , thinkphp , Yii и так далее. В основном используются контейнеры. Что касается меня, хотя я понимаю, как пишет ларавель, если я не попробую, я всегда думаю, что это не сработает.
Следующий код представляет собой простой контейнер, который я реализовал. Во многих местах это не очень хорошо обрабатывается, но этого должно быть достаточно.
php
class Container{
// The variable $binds is saved as a mapping of the name=> instance
private $binds = [];
public static $instance = null;
/**
* single case
*/
public static function getInstance(){
if(static::$instance == null){
static::$instance = new static();
return static::$instance ;
}
return static::$instance;
}
/**
* At first it was influenced by laravel, so I wrote a bind function.
* After looking at the container implementation of laravel, I was impressed by the $concrete and $abstract back-and-forth transformations.
* The following code is a little bit like the implementation in thinkphp, a little more understandable
*/
public static function bind($name,$class = null){
if($class instanceof Closure){
static::getInstance()->binds[$name] = $class;
}else if(is_object($class)){
static::getInstance()->binds[$name] = $class;
}else{
// Start making an array here, laravel seems to be separate from make and build.
static::getInstance()->make($name);
}
}
/**
* The core is the make method.
*/
public static function get($name){
return static::getInstance()->make($name);
}
/**
* Core make method
*/
public function make($name){
try{
// Find if the $this - > binds instance already exists based on the class name, and return it directly if it exists.
if(array_key_exists($name,$this->binds)){
return $this->binds[$name];
}
// Get its reflection class from the class name
$reflectClass = new ReflectionClass($name);
// Using Reflective Classes
$constructor = $reflectClass->getConstructor();
// If there is no constructor, instantiate it directly
$params = [];
if(!is_null($constructor)){
// Getting the method in the constructor
$constructorParams = $constructor->getParameters();
// var_dump($constructorParams);
// Save constructor parameters
foreach($constructorParams as $constructorParam){
// This place is mainly to determine whether the parameter is a class, and if it is constructed recursively, is it simply added to $this - > params?
if(!is_null($constructorParam->getType())){
$params[] =$this->make($constructorParam->name,$constructorParam->name);
}else{
$params[] = $constructorParam->name;
}
}
}
// An example of tectonics in this place
$class = $reflectClass->newInstanceArgs($params);
// binding
$this->binds[$name] = $class;
return $class;
}catch(ReflectionException $e){
echo $e->getMessage();
}
}
private function __construct(){}
private function __clone(){}
}
?> Вот мой тестовый файл.
name;
}
public function sayDI2Name(DI2 $di2){
// If so, the di2 method prints out before the previous string
// echo "form Test say di2 name: ".$di2->sayName();
echo "form Test say di2 name: ";
echo $di2->sayName();
}
}
class DI{
private $name = "DI";
public function __construct(DI2 $di2){}
public function sayName(){
echo $this->name;
}
}
class DI2{
private $name = "DI2";
public function __construct(){}
public function sayName(){
echo $this->name;
}
}
class DI3{
private $name = "DI3";
public function __construct(){}
public function sayName(){
echo $this->name;
}
}
class DI4{
private $name = "DI4";
public function __construct(){}
public function sayName(){
echo $this->name;
}
}
// It doesn't matter whether you want it or not.
// Container::bind('test','Test');
$test = Container::get('test');
$test->sayName();
echo "\n";
$test->sayDI2Name(new DI2());
echo "\n";
$di = Container::get('di');
$di->sayName();
echo "\n";
$di2 = Container::get('di2');
$di2->sayName();
echo "\n";
$di3 = new DI3();
Container::get('di3',$di3)->sayName();
echo "\n";
$di4 = function(){
return new DI4();
};
Container::get('di4',$di4)->sayName();
echo "\n";
?> Окончательные результаты таковы.
Оригинал: “https://developpaper.com/implementing-a-simple-di-container/”