php参数反射,PHP通过反射实现自动注入参数

现在的框架中都有一个容器, 而容器解决依赖的问题是通过反射来达到的,

首先先说明一下项目文件结构:

/ ROOT_PATH

├─src

│ ├─Controllers

│ │ └─IndexController.php

| ├─Application.php (核心,获得实例)

│ ├─Http.php

│ └─Request.php

├─vendor

│ └─autoload.php

├─composer.json

└─index.php

而我们要运行IndexController.php,而这个控制器的构造函数需要一个Request类,而Request类构造函数需要一个Http类。

IndexController.php

namespace Waitmoonman\Reflex\Controllers;

use Waitmoonman\Reflex\Request;

class IndexController

{

/**

* 注入一个 Request 类

* IndexController constructor.

* @param Request $request

*/

public function __construct(Request $request)

{

echo '我是 ' . __CLASS__ . ' 我依赖' . $request->className;

}

}

Application.php

namespace Waitmoonman\Reflex;

use Exception;

use ReflectionClass;

class Application

{

/*

* @param $class

* @param array $parameters

* @return mixed

* @throws Exception

*/

public static function make($class, $parameters = [])

{

// 通过反射获取反射类

$rel_class = new ReflectionClass($class);

// 查看是否可以实例化

if (! $rel_class->isInstantiable())

{

throw new Exception($class . ' 类不可实例化');

}

// 查看是否用构造函数

$rel_method = $rel_class->getConstructor();

// 没有构造函数的话,就可以直接 new 本类型了

if (is_null($rel_method))

{

return new $class();

}

// 有构造函数的话就获取构造函数的参数

$dependencies = $rel_method->getParameters();

// 处理,把传入的索引数组变成关联数组, 键为函数参数的名字

foreach ($parameters as $key => $value)

{

if (is_numeric($key))

{

// 删除索引数组, 只留下关联数组

unset($parameters[$key]);

// 用参数的名字做为键

$parameters[$dependencies[$key]->name] = $value;

}

}

// 处理依赖关系

$actual_parameters = [];

foreach ($dependencies as $dependenci)

{

// 获取对象名字,如果不是对象返回 null

$class_name = $dependenci->getClass();

// 获取变量的名字

$var_name = $dependenci->getName();

// 如果是对象, 则递归new

if (array_key_exists($var_name, $parameters))

{

$actual_parameters[] = $parameters[$var_name];

}

elseif (is_null($class_name))

{

// null 则不是对象,看有没有默认值, 如果没有就要抛出异常

if (! $dependenci->isDefaultValueAvailable())

{

throw new Exception($var_name . ' 参数没有默认值');

}

$actual_parameters[] = $dependenci->getDefaultValue();

}

else

{

$actual_parameters[] = self::make($class_name->getName());

}

}

// 获得构造函数的数组之后就可以实例化了

return $rel_class->newInstanceArgs($actual_parameters);

}

}

Http.php

namespace Waitmoonman\Reflex;

class Http

{

public $className;

public function __construct()

{

$this->className = __CLASS__;

}

}

Request.php

namespace Waitmoonman\Reflex;

class Request

{

public $className;

public function __construct(Http $http)

{

$this->className = __CLASS__;

$this->className = $this->className . ' -> ' . $http->className;

}

}

index.php

// 要实现自动载入

use Waitmoonman\Reflex\Application;

require 'vendor/autoload.php';

// new 一个 ReflectionClass 类, 放入需要实例的类名

$ctl = Application::make(\Waitmoonman\Reflex\Controllers\IndexController::class);

var_dump($ctl);

输出:

我是 Waitmoonman\Reflex\Controllers\IndexController 我依赖Waitmoonman\Reflex\Request -> Waitmoonman\Reflex\Http

F:\phpStudy\WWW\reflex\index.php:12:

object(Waitmoonman\Reflex\Controllers\IndexController)[9]

这就是一个完整的反射类动态注入参数的实例。

以上代码可以查看我的git仓库

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值