Home  >  Article  >  Backend Development  >  PHP reflection mechanism realizes automatic dependency injection

PHP reflection mechanism realizes automatic dependency injection

不言
不言Original
2018-04-18 09:11:471358browse

The content of this article is about the PHP reflection mechanism to achieve automatic dependency injection. It has a certain reference value. Now I share it with you. Friends in need can refer to it.

Dependency injection is also called Inversion of control should be familiar to anyone who has used frameworks. Many people think it is something very high-end when they see the name, and are daunted by it. Today I took the time to do some research and unravel its mystery. Without further ado, let’s go straight to the code;

/**
*
* 工具类,使用该类来实现自动依赖注入。
*
*/class Ioc {

    // 获得类的对象实例
    public static function getInstance($className) {

        $paramArr = self::getMethodParams($className);        return (new ReflectionClass($className))->newInstanceArgs($paramArr);
    }    /**
     * 执行类的方法
     * @param  [type] $className  [类名]
     * @param  [type] $methodName [方法名称]
     * @param  [type] $params     [额外的参数]
     * @return [type]             [description]
     */
    public static function make($className, $methodName, $params = []) {

        // 获取类的实例
        $instance = self::getInstance($className);        // 获取该方法所需要依赖注入的参数
        $paramArr = self::getMethodParams($className, $methodName);        return $instance->{$methodName}(...array_merge($paramArr, $params));
    }    /**
     * 获得类的方法参数,只获得有类型的参数
     * @param  [type] $className   [description]
     * @param  [type] $methodsName [description]
     * @return [type]              [description]
     */
    protected static function getMethodParams($className, $methodsName = '__construct') {

        // 通过反射获得该类
        $class = new ReflectionClass($className);        $paramArr = []; // 记录参数,和参数类型

        // 判断该类是否有构造函数
        if ($class->hasMethod($methodsName)) {            // 获得构造函数
            $construct = $class->getMethod($methodsName);            // 判断构造函数是否有参数
            $params = $construct->getParameters();            if (count($params) > 0) {                // 判断参数类型
                foreach ($params as $key => $param) {                    if ($paramClass = $param->getClass()) {                        // 获得参数类型名称
                        $paramClassName = $paramClass->getName();                        // 获得参数类型
                        $args = self::getMethodParams($paramClassName);                        $paramArr[] = (new ReflectionClass($paramClass->getName()))->newInstanceArgs($args);
                    }
                }
            }
        }        return $paramArr;
    }
}

The above code uses PHP’s reflection function to create a container class, and uses this class to implement the dependency injection function of other classes. The above dependency injection is divided into two types, one is dependency injection of constructor, and the other is dependency injection of method. We use the following three classes for testing.

class A {    protected $cObj;    /**
     * 用于测试多级依赖注入 B依赖A,A依赖C
     * @param C $c [description]
     */
    public function __construct(C $c) {

        $this->cObj = $c;
    }    public function aa() {

        echo 'this is A->test';
    }    public function aac() {

        $this->cObj->cc();
    }
}

class B {    protected $aObj;    /**
     * 测试构造函数依赖注入
     * @param A $a [使用引来注入A]
     */
    public function __construct(A $a) {

        $this->aObj = $a;
    }    /**
     * [测试方法调用依赖注入]
     * @param  C      $c [依赖注入C]
     * @param  string $b [这个是自己手动填写的参数]
     * @return [type]    [description]
     */
    public function bb(C $c, $b) {

        $c->cc();
        echo "\r\n";

        echo 'params:' . $b;
    }    /**
     * 验证依赖注入是否成功
     * @return [type] [description]
     */
    public function bbb() {

        $this->aObj->aac();
    }
}

class C {    public function cc() {

        echo 'this is C->cc';
    }
}
  1. Test dependency injection of constructor

// 使用Ioc来创建B类的实例,B的构造函数依赖A类,A的构造函数依赖C类。$bObj = Ioc::getInstance('B');
$bObj->bbb(); // 输出:this is C->cc , 说明依赖注入成功。// 打印$bObjvar_dump($bObj);// 打印结果,可以看出B中有A实例,A中有C实例,说明依赖注入成功。object(B)#3 (1) {
  ["aObj":protected]=>  object(A)#7 (1) {
    ["cObj":protected]=>    object(C)#10 (0) {
    }
  }
}
  1. Test method dependency injection

Ioc::make('B', 'bb', ['this is param b']);// 输出结果,可以看出依赖注入成功。this is C->ccparams:this is param b

From the above two examples, we can see that when we create an object or call a method, we don’t need to know the dependencies of the class or method at all. That class. Using the reflection mechanism can easily automatically inject the required classes for us.

Summary

Okay, do you think the above code is very simple? In fact, as long as you are familiar with the reflection mechanism of PHP, dependency injection is not difficult to implement. The above In order to facilitate understanding, the code is written simply to eliminate violence. In actual projects, it will definitely not be so simple. For example, the injected classes and parameters will be configured. For example, the instantiated classes will be cached so that the class will be needed next time. instance, you can use it directly without reinitializing it, etc. But I believe that once you understand the principles, you can improve the rest according to the needs of the project.

Related recommendations:

PHP reflection practical application example sharing

Detailed explanation of the private method in the execution class of the PHP reflection method

The above is the detailed content of PHP reflection mechanism realizes automatic dependency injection. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn