博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Laravel源码阅读(前奏-反射实例化对象)
阅读量:6295 次
发布时间:2019-06-22

本文共 2988 字,大约阅读时间需要 9 分钟。

说明

Laravel的核心容器,有一部分就是利用反射来实现依赖注入时类的实例化。这是一个简化版示例。

代码

测试用的类

/** * 坦克标准: 必须能开火 */interface Tank{    public function fire();}/** * 59坦克,使用100毫米炮 */class Tank59 implements Tank{    private $gun = 100;    public function fire()    {        echo $this->gun . PHP_EOL;    }}/** * 59加强版,可以使用100毫米炮或120毫米炮,默认120毫米炮 */class Tank59Plus implements Tank{    private $gun;    public function __construct($gun = 120)    {        if($gun != 100 && $gun != 120) {            throw new Exception('口径不合适');        }        $this->gun = $gun;    }    public function fire()    {        echo $this->gun . PHP_EOL;    }}/** * 59超级版,可以使用任意口径的炮,必须提供一门火炮 */class Tank59Super implements Tank{    private $gun;    public function __construct($gun)    {        $this->gun = $gun;    }    public function fire()    {        echo $this->gun . PHP_EOL;    }}/** * 坦克营,装备59和59加强版,必须提供59和59加强版 */class TankArmy implements Tank{    private $tank59;    private $tank59Plus;    public function __construct(Tank59 $tank59, Tank59Plus $tank59Plus)    {        $this->tank59 = $tank59;        $this->tank59Plus = $tank59Plus;    }    public function fire()    {        echo $this->tank59->fire();        echo $this->tank59Plus->fire();    }}

容器

/** * 兵工厂 */class Factory{    /**     * 创建实体对象     */    public static function build($blueprint)    {        //反射,获取类细节        $reflector = new ReflectionClass($blueprint);        //无法创建的类,比如接口,抽象类        if(!$reflector->isInstantiable()) {            throw new Exception('提供的不是坦克图纸,不能制造');        }        //获取类的构造方法        $constructor = $reflector->getConstructor();        if (is_null($constructor)) {            //没有构造方法,直接new            return new $blueprint;        }        $parameters = [];        //获取构造方法依赖的参数        $dependencies = $constructor->getParameters();        foreach ($dependencies as $dependency) {                 if(is_null($dependency->getClass())) {                //依赖参数不是对象                //如果构造方法参数有默认值,获取默认值                if($dependency->isDefaultValueAvailable()) {                    $parameters[] = $dependency->getDefaultValue();                }            }            else {                //依赖参数是对象,递归创建                $parameters[] = self::build($dependency->getClass()->name);            }        }        if(!$parameters) {            //有构造方法且构造方法有参数,却没有可以提供的实参,无法创建            throw new Exception('坦克缺少必要的零件,不能制造');        }        else {            //使用反射提供的方法创建对象,传入参数            return  $reflector->newInstanceArgs($parameters);        }    }}

测试

Tank

$tank = Factory::build(Tank::class);echo $tank->fire();//输出//PHP Fatal error:  Uncaught Exception: 提供的不是坦克图纸,不能制造

Tank59

$tank = Factory::build(Tank59::class);echo $tank->fire();//输出//100

Tank59Plus

$tank = Factory::build(Tank59Plus::class);echo $tank->fire();//输出//120

Tank59Super

$tank = Factory::build(Tank59Super::class);echo $tank->fire();//输出//Fatal error: Uncaught Exception: 坦克缺少必要的零件,不能制造

TankArmy

$tank = Factory::build(TankArmy::class);echo $tank->fire();//输出//100//120

转载地址:http://tpvta.baihongyu.com/

你可能感兴趣的文章
vim使用点滴
查看>>
embedded linux学习中几个需要明确的概念
查看>>
mysql常用语法
查看>>
Morris ajax
查看>>
【Docker学习笔记(四)】通过Nginx镜像快速搭建静态网站
查看>>
ORA-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务
查看>>
<转>云主机配置OpenStack使用spice的方法
查看>>
java jvm GC 各个区内存参数设置
查看>>
[使用帮助] PHPCMS V9内容模块PC标签调用说明
查看>>
基于RBAC权限管理
查看>>
数学公式的英语读法
查看>>
留德十年
查看>>
迷人的卡耐基说话术
查看>>
PHP导出table为xls出现乱码解决方法
查看>>
PHP问题 —— 丢失SESSION
查看>>
Java中Object类的equals()和hashCode()方法深入解析
查看>>
数据库
查看>>
dojo.mixin(混合进)、dojo.extend、dojo.declare
查看>>
Python 数据类型
查看>>
iOS--环信集成并修改头像和昵称(需要自己的服务器)
查看>>