相关概念:
依赖注入:
class test1(Base $base){
}
test1 的依赖注入为Base类,看有的书也叫组合,说是底层代码最好用组合,顶端代码最好用继承。
反射:
用字符串作为类名生成相关对象,方法有很多:https://blog.csdn.net/luyaran/article/details/84339363
这里仅用反射API,包括 ReflectionClass、ReflectionMethod、ReflectionParameter、ReflectionFunction
代码如下:
error_reporting(E_ALL);
class Base {
public function index($text) {
echo 'base:' . $text;
}
}
class Con1 {
public function __construct(Base $base) {
$base->index(__CLASS__);
}
public function test($text) {
echo "Con1:" . $text;
}
}
class Con2 {
public function Con2(Base $base) {
$base->index(__CLASS__);
}
public function index($text) {
echo "Con2:" . $text;
}
}
class Container {
//容器列表
public $conList = [];
public function __construct() {
$this->initList();
}
//数据初始化
private function initList() {
//容器名 => 容器类 注入类
//::class 不可动态编译
$this->conList = [
'con1' => ['class' => 'con1'::class, 'param' => ['Base'::class]],
];
}
//获取容器
public function getCon($conName) {
if (isset($this->conList[$conName])) {
$config = $this->conList[$conName];
$objClass = $this->getClass($config['class'], $config['param']);
return $objClass;
} else {
return false;
}
}
//注册新容器
public function register($conName, $className, $param = []) {
if (isset($this->conList[$conName])) {
return true;
}
$this->conList[$conName] = ['class' => $className, 'param' => $param];
}
//新建容器对象
private function getClass($className, $params = []) {
$class = new ReflectionClass($className);
$constructInfo = $class->getConstructor();
$constructName = $constructInfo->name;
$construct = $class->getMethod($constructName);
$conParams = $construct->getParameters();
$paramArr = [];
if (count($conParams) > 0) {
foreach ($conParams as $key => $value) {
$parCLassName = $value->getClass()->name;
if ($parCLassName == $params[$key]) {
$paramArr[] = (new ReflectionClass($params[$key]))->newInstance();
}
}
}
$conObjRef = new ReflectionClass($className);
$conObj = $conObjRef->newInstanceArgs($paramArr);
return $conObj;
}
}
//test
$con = new Container();
$con->getCon('con1')->test('test1');
$con->register('con2', 'Con2'::class, ['Base'::class]);
$con->getCon('con2')->index('test2');
解释:
初始化容器列表,可以设置新容器,添加到列表中。获取实例时创建实例对象,可根据设置进行依赖注入。
注:
::class 不支持动态编译
参考: