<?php
class ioc
{
protected static $registry = [];
public static function bind($name, callable $resolver) //传入类名和类对象实例
{
static::$registry[$name] = $resolver;
}
public static function make($name) //静态工厂方法
{
if (isset(static::$registry[$name])) {
$resolver = static::$registry[$name];
return $resolver(); //实例化
}
throw new exception('alias does not exist in the ioc registry.');
}
}
<?php //依赖关系:company->department->group
class group
{
public function dosomething()
{
echo __class__.":".'hello', '|';
}
}
class department
{
private $group;
public function __construct(group $group)
{
$this->group = $group;
}
public function dosomething()
{
$this->group->dosomething();
echo __class__.":".'hello', '|';
}
}
class company
{
private $department;
public function __construct(department $department)
{
$this->department = $department;
}
public function dosomething()
{
$this->department->dosomething();
echo __class__.":".'hello', '|';
}
}
ioc容器的内部实现:
<?php
class container
{
private $s = array();
public function __set($k, $c)
{
$this->s[$k] = $c;
}
public function __get($k)
{
return $this->build($this->s[$k]);
}
/**
* 自动绑定(autowiring)自动解析(automatic resolution)
*
* @param string $classname
* @return object
* @throws exception
*/
public function build($classname)
{
// 如果是匿名函数(anonymous functions),也叫闭包函数(closures)
if ($classname instanceof closure) {
// 执行闭包函数,并将结果
return $classname($this);
}
/*通过反射获取类的内部结构,实例化类*/
$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.');
}
}
require_once "./testclass.php"; //开始测试,先测试已知依赖关系的情况
$c = new container();
$c->department = 'department';
$c->company = function ($c) {
return new company($c->department);
};
// 从容器中取得company
$company = $c->company;
$company->dosomething(); //输出: group:hello|department:hello|company:hello|
// 测试未知依赖关系,直接使用的方法
$di = new container();
$di->company = 'company';
$company = $di->company;
$company->dosomething();//输出: group:hello|department:hello|company:hello|