Laravel框架源码解析之反射的使用详解


Posted in PHP onMay 14, 2020

本文实例讲述了Laravel框架源码解析之反射的使用。分享给大家供大家参考,具体如下:

前言

PHP的反射类与实例化对象作用相反,实例化是调用封装类中的方法、成员,而反射类则是拆封类中的所有方法、成员变量,并包括私有方法等。就如“解刨”一样,我们可以调用任何关键字修饰的方法、成员。当然在正常业务中是建议不使用,比较反射类已经摒弃了封装的概念。

本章讲解反射类的使用及Laravel对反射的使用。

反射

反射类是PHP内部类,无需加载即可使用,你可以通过实例化 ReflectionClass 类去使用它。

方法

这里列举下PHP反射类常用的方法

方法名 注释
ReflectionClass::getConstant 获取定义过的一个常量
ReflectionClass::getConstants 获取一组常量
ReflectionClass::getConstructor 获取类的构造函数
ReflectionClass::getDefaultProperties 获取默认属性
ReflectionClass::getDocComment 获取文档注释
ReflectionClass::getEndLine 获取最后一行的行数
ReflectionClass::getFileName 获取定义类的文件名
ReflectionClass::getInterfaceNames 获取接口(interface)名称
ReflectionClass::getMethods 获取方法的数组
ReflectionClass::getModifiers 获取类的修饰符
ReflectionClass::getName 获取类名
ReflectionClass::getNamespaceName 获取命名空间的名称
ReflectionClass::getParentClass 获取父类

等等等等.... 所有关于类的方法、属性及其继承的父类、实现的接口都可以查询到。
详细文档请参考官网: http://php.net/manual/zh/class.reflectionclass.php

栗子

<?php
 namespace A\B;
 
 class Foo { }
 
 $function = new \ReflectionClass('stdClass');
 
 var_dump($function->inNamespace());
 var_dump($function->getName());
 var_dump($function->getNamespaceName());
 var_dump($function->getShortName());
 
 $function = new \ReflectionClass('A\\B\\Foo');
 
 var_dump($function->inNamespace());
 var_dump($function->getName());
 var_dump($function->getNamespaceName());
 var_dump($function->getShortName());
?>

输出结果

bool(false)
string(8) "stdClass"
string(0) ""
string(8) "stdClass"

bool(true)
string(7) "A\B\Foo"
string(3) "A\B"
string(3) "Foo"

Laravel

Laravel在实现服务容器加载时使用了反射类。现在我们开启“解刨”模式

入口文件

index.php

$app = require_once __DIR__.'/../bootstrap/app.php';

/*
|--------------------------------------------------------------------------
| Run The Application
|--------------------------------------------------------------------------
|
| Once we have the application, we can handle the incoming request
| through the kernel, and send the associated response back to
| the client's browser allowing them to enjoy the creative
| and wonderful application we have prepared for them.
|
*/

$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

$response = $kernel->handle(
 $request = Illuminate\Http\Request::capture()
);

$response->send();

$kernel->terminate($request, $response);

是引用语句发生的下一行调用了make方法。各位很清楚,make方法用于解析类,所有make方法的实现一定是在引用的文件内。

bootstrap\app.php

$app = new Illuminate\Foundation\Application(
 realpath(__DIR__.'/../')
);

laravel开始加载它的核心类,所有的实现从 Illuminate\Foundation\Application 开始。

Illuminate\Foundation\Application

public function make($abstract, array $parameters = [])
{
  $abstract = $this->getAlias($abstract);

  if (isset($this->deferredServices[$abstract]) && ! isset($this->instances[$abstract])) {
   $this->loadDeferredProvider($abstract);
  }

  return parent::make($abstract, $parameters);
}

在核心类中你可能准确的查找到make方法的存在,它加载了服务提供者随后调用了父类的方法make,要知道作为独立的模块 “服务容器”是绝对不能写在核心类的。懂点设计模式的都很清楚。

Illuminate\Container\Container

$api = $this->app->make('HelpSpot\API',['id'=>1]); 为例来讲解

// 真正的make方法,它直接调用了resolve继续去实现make的功能
// $abstract = 'HelpSpot\API'
public function make($abstract, array $parameters = [])
{
 // $abstract = 'HelpSpot\API'
 return $this->resolve($abstract, $parameters);
}

...

protected function resolve($abstract, $parameters = [])
{
 ...
 // 判断是否可以合理反射
 // $abstract = 'HelpSpot\API'
 if ($this->isBuildable($concrete, $abstract)) {
  // 实例化具体实例 (实际并不是实例化,而是通过反射“解刨”了)
  $object = $this->build($concrete);
 } else {
  $object = $this->make($concrete);
 }
 ...
}

public function build($concrete)
{
  // $concrete = 'HelpSpot\API'
  if ($concrete instanceof Closure) {
   return $concrete($this, $this->getLastParameterOverride());
  }
  // 实例化反射类
  $reflector = new ReflectionClass($concrete);

  // 检查类是否可实例化
  if (! $reflector->isInstantiable()) {
   return $this->notInstantiable($concrete);
  }

  $this->buildStack[] = $concrete;

  // 获取类的构造函数
  $constructor = $reflector->getConstructor();
  
  if (is_null($constructor)) {
   array_pop($this->buildStack);

   return new $concrete;
  }

  $dependencies = $constructor->getParameters();

  $instances = $this->resolveDependencies(
   $dependencies
  );

  array_pop($this->buildStack);
   
  // 从给出的参数创建一个新的类实例。
  return $reflector->newInstanceArgs($instances);
}

可见一个服务容器就加载成功了。

希望本文所述对大家基于Laravel框架的PHP程序设计有所帮助。

PHP 相关文章推荐
Zend framework处理一个http请求的流程分析
Feb 08 PHP
关于Iframe如何跨域访问Cookie和Session的解决方法
Apr 15 PHP
作为PHP程序员应该了解MongoDB的五件事
Jun 03 PHP
php var_export与var_dump 输出的不同
Aug 09 PHP
解密ThinkPHP3.1.2版本之模块和操作映射
Jun 19 PHP
php简单图像创建入门实例
Jun 10 PHP
如何使用php脚本给html中引用的js和css路径打上版本号
Nov 18 PHP
对比分析php中Cookie与Session的异同
Feb 19 PHP
简单介绍PHP非阻塞模式
Mar 03 PHP
PHP程序中的文件锁、互斥锁、读写锁使用技巧解析
Mar 21 PHP
PHP简单读取PDF页数的实现方法
Jul 21 PHP
使用tp框架和SQL语句查询数据表中的某字段包含某值
Oct 18 PHP
PHP 数组操作详解【遍历、指针、函数等】
May 13 #PHP
ThinkPHP5 框架引入 Go AOP,PHP AOP编程项目详解
May 12 #PHP
php中用unset销毁变量并释放内存
May 10 #PHP
php屏蔽错误及提示的方法
May 10 #PHP
php判断数组是否为空的实例方法
May 10 #PHP
通过PHP实现获取访问用户IP
May 09 #PHP
如何通过PHP实现Des加密算法代码实例
May 09 #PHP
You might like
php数组合并array_merge()函数使用注意事项
2014/06/19 PHP
php遍历树的常用方法汇总
2015/06/18 PHP
Javascript 学习书 推荐
2009/06/13 Javascript
JavaScript中清空数组的三种方法分享
2011/04/07 Javascript
JQuery入门——用one()方法绑定事件处理函数(仅触发一次)
2013/02/05 Javascript
Jquery中基本选择器用法实例详解
2015/05/18 Javascript
javascript实现自动填写表单实例简析
2015/12/02 Javascript
AngularJS实现全选反选功能
2015/12/08 Javascript
Jquery跨域获得Json的简单实例
2016/05/18 Javascript
深入理解MVC中的时间js格式化
2016/05/19 Javascript
JS实现直接运行html代码的方法
2017/03/13 Javascript
基于zepto.js实现手机相册功能
2017/07/11 Javascript
用vue2.0实现点击选中active其他选项互斥的效果
2018/04/12 Javascript
JavaScript获取页面元素的常用方法详解
2019/09/28 Javascript
JS 设计模式之:工厂模式定义与实现方法浅析
2020/05/06 Javascript
vue 表单输入框不支持focus及blur事件的解决方案
2020/11/17 Vue.js
js删除对象中的某一个字段的方法实现
2021/01/11 Javascript
jquery实现穿梭框功能
2021/01/19 jQuery
对python中return和print的一些理解
2017/08/18 Python
Python实现基于PIL和tesseract的验证码识别功能示例
2018/07/11 Python
django实现模型字段动态choice的操作
2020/04/01 Python
python 实现图像快速替换某种颜色
2020/06/04 Python
深入理解css属性的选择对动画性能的影响
2016/04/20 HTML / CSS
HTML5 Canvas中使用用路径描画圆弧
2015/01/01 HTML / CSS
薇诺娜官方网上商城:专注敏感肌肤
2017/05/25 全球购物
美国优质马术服装购买网站:Breeches.com
2019/12/16 全球购物
大学生入党思想汇报
2014/01/01 职场文书
2014信息公开实施方案
2014/02/22 职场文书
网站美工岗位职责
2014/04/02 职场文书
省文明单位申报材料
2014/05/08 职场文书
2014学校领导四风问题对照检查材料思想汇报
2014/09/22 职场文书
教师个人自我剖析材料
2014/09/29 职场文书
业务员岗位职责范本
2015/04/03 职场文书
2015暑期工社会实践报告
2015/07/13 职场文书
SQL Server中常用截取字符串函数介绍
2022/03/16 SQL Server
Python中使用Opencv开发停车位计数器功能
2022/04/04 Python