1. 程式人生 > >PHP反射實現對類的方法依賴注入和建構函式依賴注入

PHP反射實現對類的方法依賴注入和建構函式依賴注入

前段時間一直在看tp5 發現他內部實現了控制器的依賴注入。。下面 我通過程式碼來說明一下是怎麼實現的。

首先我們準備好幾個類檔案  我們先看目錄安排


其中 start.php是啟動檔案

<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/4/17
 * Time: 21:04
 */

header("Content-type: text/html; charset=utf-8");
require 'auto1.php';
require 'auto2.php';
require 'auto3.php';
require 'auto4.php';

class App{

    public static function run()
    {
        $class = 'auto1';
        $sh1 = 'sh1';
        $sh3 = 'sh3';

        self::exec($class,$sh1);

    }

    //執行反射類方法。
    public static function exec($class,$methodname)
    {
        //注入的實質是通過php的反射類 來執行被注入類的行為
        //通過反射 可以得到類的一些資訊 主要包括方法 屬性
        //通過注入 我們可以實現類對方法和構造方法的依賴。下面我舉例說明
        //1.先肯定是從一個類的建構函式開始。
        //2.利用反射得到這個類的建構函式 在執行
        $reflect     = new \ReflectionClass($class);
        $constructor = $reflect->getConstructor();
        $p1 = self::getParamValue($constructor);
        //執行被反射類的建構函式 實現建構函式的依賴注入
        $instance = $reflect->newInstanceArgs($p1);
        //執行注入類的方法。
        $reflect = new \ReflectionMethod($class, $methodname);
        $p2 = self::getParamValue($reflect);
        //執行方法注入。
        $reflect->invokeArgs($instance, $p2);
    }
    //這個類用來 反射出當前注入類所在的引數。
    private static function getParamValue($reflect,$avgs=[])
    {
        if ($reflect->getNumberOfParameters() > 0)
        {
            foreach ($reflect->getParameters() as $param) {
                $param_type = $param->getClass();//獲取當前注入物件的型別提示
                $param_value = $param->getName();//獲取引數名稱
                if($param_type)
                {
                    //表示是物件型別的引數
                    $avgs[] = new $param_value;
                }
                else
                {
                    $avgs[] = $param_value;
                }
            }
        }
        return $avgs;
    }
}
//執行應用程式
App::run();

auto1.php

<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/4/17
 * Time: 21:30
 */

class auto1{

    public function __construct(auto4 $auto4)
    {
        $auto4->sh();
    }

    public function sh1(){
        echo '我是沒有引數的方法sh1,我被執行了<br>';
    }

    public function sh3(auto2 $auto2,auto3 $auto3)
    {
        $auto2->sh();
        $auto3->sh();
    }
}

auto2.php

<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/4/17
 * Time: 21:31
 */

class auto2{
    public function sh(){
        echo '我是auto2,我被執行到了,說明依賴注入成功了<br>';
    }
}

auto3.php

<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/4/17
 * Time: 23:18
 */

class auto3{
    public function sh(){
        echo '我是auto3,我被執行到了,說明依賴注入成功了<br>';
    }
}

auto4.php

<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/4/18
 * Time: 21:03
 */

class auto4{
    public function sh(){
        echo '我是auto4,我被執行到了,說明依賴注入成功了<br>';
    }
}

呼叫方式



執行效果





執行效果



這樣就實現了。你可以想象一下 tp5的控制器是不是就是我們這裡的auto1這個類啊。我剝離了它的依賴程式碼,核心就是我那個App類的2個方法了。