如何用 PHP 的反射类实现依赖注入

ReflectionClass 提供关于类的信息,它有什么属性、哪些方法、方法有哪些参数,类文件的路径是什么等等。

我们先定义两个类,然后熟悉下 ReflectionClass 的一些用法。最后我们写一个简单的函数来实现依赖注入。

ReflectionClass 的一些方法

<?php

// Class Point
Class Point
{
    public $x;
    public $y;

    public function __construct($x=0, $y=0)
    {
        $this->x = $x;
        $this->y = $y;
    }
}

Class Circle
{
    // 半径
    public $radius;

    // 圆心点
    public $center;

    const PI = 3.14;

    public function __construct(
        Point $point,
        $radius = 1
    ){
        $this->center = $point;
        $this->radius = $radius;
    }

    public function printCenter()
    {
        printf('center coordinate is (%d, %d)', $this->center->x, $this->center->y);
    }

    public function area()
    {
        return self::PI * pow($this->radius, 2);
    }

}


// examples
$reflectionClass = new reflectionClass(Circle::class);
var_dump($reflectionClass);

// 反射出类的常量
var_dump($reflectionClass->getConstants());
// 通过反射获取属性
var_dump($reflectionClass->getProperties());
// 反射出类中定义的方法
var_dump($reflectionClass->getMethods());
// 文件路径
var_dump($reflectionClass->getFileName());


$constructor = $reflectionClass->getConstructor();
var_dump($constructor);

$parameters = $constructor->getParameters();
var_dump($parameters);

(结果就忽略掉了)

依赖注入

<?php

// Class Point
Class Point
{
    public $x;
    public $y;

    public function __construct($x=0, $y=0)
    {
        $this->x = $x;
        $this->y = $y;
    }
}

Class Circle
{
    // 半径
    public $radius;

    // 圆心点
    public $center;

    const PI = 3.14;

    public function __construct(
        Point $point,
        $radius = 1
    ){
        $this->center = $point;
        $this->radius = $radius;
    }

    public function printCenter()
    {
        printf('center coordinate is (%d, %d)', $this->center->x, $this->center->y);
    }

    public function area()
    {
        return self::PI * pow($this->radius, 2);
    }

}




// 创建类的常规方法
// $p1 = new Point(2,2);
// $c1 = new Circle($p1, 2);

// $c1->printCenter();
// echo $c1->area();


// dependency injection
function make($className)
{
    $reflectionClass = new reflectionClass($className);
    $constructor = $reflectionClass->getConstructor();
    $parameters = $constructor->getParameters();
    $dependencies = getDependencies($parameters);

    return $reflectionClass->newInstanceArgs($dependencies);
}

// 依赖解析
function getDependencies($parameters)
{
    $dependencies = [];
    foreach ($parameters as $parameter) {
        $dependency = $parameter->getClass();

        // var_dump($dependency);
        // 第二个参数 radius 就没有类
        if (is_null ($dependency)) {

            if ($parameter->isDefaultValueAvailable()) {
                $dependencies[] = $parameter->getDefaultValue();
            } else {
                // 简化的处理
                $dependencies[] = '0';
            }

        } else {
            // 递归解析出依赖类的对象
            $dependencies[] = make($parameter->getClass()->name);
        }
    }
    return $dependencies;
}

$c2 = make('Circle');
$area = $c2->area();
var_dump($c2, $area);

参考

ReflectionClass php mannual
参考链接

发表评论

电子邮件地址不会被公开。 必填项已用*标注