php 的一個依賴注入容器, 說白了,就是用php 的反射類,來在運行的時候動態的分析類具有的函數,以及動態分析函數的參數, 從而實例化類,並執行類的方法。
另外,php 中的 typehint 還是很有用的,反射的時候就有用到!





下面貼出代碼:
<?php
class Bim
{
public function doSomething()
{
echo __METHOD__, '|';
}
}
class Bar
{
private $bim;
public function __construct(Bim $bim)
{
$this->bim = $bim;
}
public function doSomething()
{
$this->bim->doSomething();
echo __METHOD__, '|';
}
}
class Foo
{
private $bar;
public function __construct(Bar $bar)
{
$this->bar = $bar;
}
public function doSomething()
{
$this->bar->doSomething();
echo __METHOD__;
}
}
class Container
{
private $s = array();
public function __set($k, $c)
{
$this->s[$k] = $c;
}
public function __get($k)
{
// return $this->s[$k]($this);
return $this->build($this->s[$k]);
}
/**
* 自動綁定(Autowiring)自動解析(Automatic Resolution)
*
* @param string $className
* @return object
* @throws Exception
*/
public function build($className)
{
echo "<pre>";var_dump($className);
// 如果是匿名函數(Anonymous functions),也叫閉包函數(closures)
if ($className instanceof Closure) {
// 執行閉包函數,並將結果
return $className($this);
}
/** @var ReflectionClass $reflector */
$reflector = new ReflectionClass($className);
// 檢查類是否可實例化, 排除抽象類abstract和對象接口interface
if (!$reflector->isInstantiable()) {
throw new Exception("Can't instantiate this.");
}
/** @var ReflectionMethod $constructor 獲取類的構造函數 */
$constructor = $reflector->getConstructor();
// 若無構造函數,直接實例化並返回
if (is_null($constructor)) {
return new $className;
}
// 取構造函數參數,通過 ReflectionParameter 數組返回參數列表
$parameters = $constructor->getParameters();
// 遞歸解析構造函數的參數
$dependencies = $this->getDependencies($parameters);
// 創建一個類的新實例,給出的參數將傳遞到類的構造函數。
return $reflector->newInstanceArgs($dependencies);
}
/**
* @param array $parameters
* @return array
* @throws Exception
*/
public function getDependencies($parameters)
{
$dependencies = [];
/** @var ReflectionParameter $parameter */
foreach ($parameters as $parameter) {
/** @var ReflectionClass $dependency */
$dependency = $parameter->getClass();
if (is_null($dependency)) {
// 是變量,有默認值則設置默認值
$dependencies[] = $this->resolveNonClass($parameter);
} else {
// 是一個類,遞歸解析
$dependencies[] = $this->build($dependency->name);
}
}
return $dependencies;
}
/**
* @param ReflectionParameter $parameter
* @return mixed
* @throws Exception
*/
public function resolveNonClass($parameter)
{
// 有默認值則返回默認值
if ($parameter->isDefaultValueAvailable()) {
return $parameter->getDefaultValue();
}
throw new Exception('I have no idea what to do here.');
}
}
// ----
//$c = new Container();
//$c->bar = 'Bar';
//$c->foo = function ($c) {
// return new Foo($c->bar);
//};
//// 從容器中取得Foo
//$foo = $c->foo;
//$foo->doSomething(); // Bim::doSomething|Bar::doSomething|Foo::doSomething
///*// ----
$di = new Container();
//
$di->foo = 'Foo';
//
///** @var Foo $foo */
$foo = $di->foo;
//
var_dump($foo);exit;
echo "<pre>";var_dump($foo->doSomething());
var_dump( get_class($foo));
die();
///*
//Foo#10 (1) {
// private $bar =>
// class Bar#14 (1) {
// private $bim =>
// class Bim#16 (0) {
// }
// }
//}
//*/
//
$foo->doSomething(); // Bim::doSomething|Bar::doSomething|Foo::doSomething*/
