您的位置:首页 > 编程语言 > PHP开发

php反射和laravel依赖注入

2019-04-04 17:56 676 查看

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

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代码的依赖注入…

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: