php反射和laravel依赖注入

什么是依赖注入?
耦合性很强的例子:

class A {
    public function __construct() {
        //  A类的内部,依赖了B类
        $this->b = new B();
    }
    public function printStrA(){
        $this->b->printStrB();
    }
}
class B{
    public function __construct() {
    }
    public function printStrB(){
        echo 'this is string';
    }
}
$obj = new A;
$obj->printStrA();

耦合性较弱的例子,传入对象当参数,这就是依赖注入.

<?php 
class A {
    public function __construct(B $par) { 
        $this->b = $par;
    }
    public function printStrA(){
        $this->b->printStrB();
    }
}
class B{
    public function __construct() {
    }
    public function printStrB(){
        echo 'this is string';
    }
}
$obj = new A(new B()); 
$obj->printStrA();

laravel中通过依赖注入和反射来完成功能.
下面这个例子介绍下反射类

class Test{
    public function __construct(Persona $p1, Personb $p2) {
        echo $p1->printStr()," ",$p2->printStr()," ";
    }
    function printString(){
        echo 'test';
        return;
    }
}

class Persona {

    function printStr() {
        echo 'persona';
    }
}

class Personb {

    function printStr(){
        echo 'personb';
    }
}
$obj = new Test(new Persona(), new Personb());
//下面是反射
$reflector = new ReflectionClass('Test');// 可以是Test或者$obj作为参数
$constructor = $reflector->getConstructor();	

$dependencies = $constructor->getParameters();// 获取构造器里面的参数
$parArr = array();
foreach ($dependencies as $depend){		
    // $depend->getClass()->name 获取类名称
	$className=$depend->getClass()->name;
	$parArray[] = new $className();
} 
$refNewObj = $reflector->newInstanceArgs($parArray);
$refNewObj->printString();

下面这个是对laravel简化的,实现了容器完成依赖注入.

interface Visit{
	public function go();
}
class Leg implements Visit{
	public function go(){echo 'leg';}
}
class Car implements Visit{
	public function go(){echo 'car';}
}
class Train implements Visit{
	public function go(){echo 'train';}
} 

class Container{
	protected $bindings=[];
	//绑定接口和生成相应实例的回调函数
	public function bind($abstract,$concrete=null,$shared=false){
		if(!$concrete instanceof Closure){
			//如果提供的参数不是回调函数,则产生默认的回调函数 
			$concrete=$this->getClosure($abstract,$concrete);
		}
		$this->bindings[$abstract]=compact('concrete','shared'); 
	}
	//默认生成实例的回调函数
	protected function getClosure($abstract,$concrete){
		//生成实例的回调函数,$c一般为Ioc容器对象,在调用回调生成实例时提供
		//既build函数中的$concrete($this)  
		return function($c) use ($abstract,$concrete){	
			$method=($abstract==$concrete)?'build':'make';
			//调用的是容器的build或make方法生成实例
			return $c->$method($concrete);
		};
	}
	//生成实例对象,首先解决接口和要实例化类之间的依赖关系
	public function make($abstract){
		
		$concrete=$this->getConcrete($abstract);echo "<pre>";var_dump($abstract)."<hr>"; 
		if($this->isBuildable($concrete,$abstract)){
 			$object=$this->build($concrete);
		}else{	
			$object=$this->make($concrete);
		}
		return $object;
	}

	protected function isBuildable($concrete,$abstract){
		return $concrete===$abstract || $concrete instanceof Closure;
	}
	//获取绑定的回调函数
	protected function getConcrete($abstract){  
		if(!isset($this->bindings[$abstract])){	
			return $abstract;
		} 
		return $this->bindings[$abstract]['concrete'];
	}
	//实例化对象
	public function build($concrete){ 
			
		if($concrete instanceof Closure){
			return $concrete($this);	
		}
		
		$reflector=new ReflectionClass($concrete);
		
		//是否可实例化
		if(!$reflector->isInstantiable()){
			echo $message="Traget [$concrete] is not instantiable";
		}
		
		$constructor=$reflector->getConstructor(); 
		if(is_null($constructor)){
			return new $concrete;
		}
		$dependencies=$constructor->getParameters();
		
		$instances=$this->getDependencies($dependencies);//
		return $reflector->newInstanceArgs($instances);
	}
	//解决通过反射机制实例化对象时的依赖
	protected function getDependencies($parameters){
		$dependencies=[];	
		foreach($parameters as $parameter){
			$dependency=$parameter->getClass();
			if(is_null($dependency)){
				$dependencies[]=null;
			}else{ 
				$dependencies[]=$this->resolveClass($parameter);
			}

		}
		return (array) $dependencies;
	}
	protected function resolveClass(ReflectionParameter $parameter){  
		return $this->make($parameter->getClass()->name);
	}
}

class Traveller{
	protected $trafficTool;
	public function __construct(Visit $trafficTool){
		$this->trafficTool=$trafficTool;
	}
	public function visitTibet(){	
		$this->trafficTool->go();
	}
}
//实例化Ioc容器
$app=new Container();
//完成容器的填充
$app->bind("Visit","Train");;
$app->bind("traveller","Traveller");
//通过容器实例依赖注入,完成类的实例化
$tra=$app->make("traveller");
$tra->visitTibet();

die;

后续补充laravel代码的依赖注入…

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值