前言

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/clas...

栗子


<?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);
}

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

致谢

感谢你看到这里,本篇文章源码解析靠个人理解。如有出入请拍砖。

希望本篇文章可以帮到你。谢谢

原文地址:https://segmentfault.com/a/1190000016480587

Laravel源码解析之反射的使用的更多相关文章

  1. laravel源码解析

    本专栏系列文章已经收录到 GitBooklaravel源码解析 Laravel Passport——OAuth2 API 认证系统源码解析(下)laravel源码解析 Laravel Passport ...

  2. Laravel源码解析--看看Lumen到底比Laravel轻在哪里

    在前面一篇<Laravel源码解析--Laravel生命周期详解>中我们利用xdebug详细了解了下Laravel一次请求中到底做了哪些处理.今天我们跟 Lumen 对比下,看看 Lume ...

  3. Laravel源码解析之model(代码)

    本篇文章给大家带来的内容是关于Laravel源码解析之model(代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 前言 提前预祝猿人们国庆快乐,吃好.喝好.玩好,我会在电视上看 ...

  4. Laravel源码解析 — 服务容器

    前言 本文对将系统的对 Laravel 框架知识点进行总结,如果错误的还望指出 阅读书籍 <Laravel框架关键技术解析> 陈昊 学习课程 Laravel5.4快速开发简书网站 轩脉刃 ...

  5. Laravel源码解析之从入口开始

    前言 提升能力的方法并非使用更多工具,而是解刨自己所使用的工具.今天我们从Laravel启动的第一步开始讲起. 入口文件 laravel是单入口框架,所有请求必将经过index.php define( ...

  6. Laravel框架下路由的使用(源码解析)

    本篇文章给大家带来的内容是关于Laravel框架下路由的使用(源码解析),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 前言 我的解析文章并非深层次多领域的解析攻略.但是参考着开发文 ...

  7. laravel 读写分离源码解析

    前言:上一篇我们说了<laravel 配置MySQL读写分离>,这次我们说下,laravel的底层代码是怎样实现读写分离的.   一.实现原理 说明: 1.根据 database.php ...

  8. Laravel学习笔记之Session源码解析(上)

    说明:本文主要通过学习Laravel的session源码学习Laravel是如何设计session的,将自己的学习心得分享出来,希望对别人有所帮助.Laravel在web middleware中定义了 ...

  9. myBatis源码解析-反射篇(4)

    前沿 前文分析了mybatis的日志包,缓存包,数据源包.源码实在有点难顶,在分析反射包时,花费了较多时间.废话不多说,开始源码之路. 反射包feflection在mybatis路径如下: 源码解析 ...

随机推荐

  1. nyoj13-Fibonacci数

    Fibonacci数 时间限制:3000 ms  |  内存限制:65535 KB 难度:1 描述 无穷数列1,1,2,3,5,8,13,21,34,55...称为Fibonacci数列,它可以递归地 ...

  2. springboot 不使用前端模板直接跳转页面

    1.创建springboot项目 2.在resource 下创建pages文件夹,存放所有页面 3.编写后台代码 4.访问http://localhost:8080/index,即可跳转到页面

  3. ActiveMQ 整合 spring

    一.添加 jar 包 <dependency> <groupId>org.apache.activemq</groupId> <artifactId>a ...

  4. ioremap映射函数

    一.ioremap() 函数 Linux在io.h头文件中声明了函数ioremap(),用来将I/O内存资源的物理地址映射到核心虚地址空间(3GB-4GB)中(这里是内核空间),原型如下: 1.ior ...

  5. js 阻止冒泡

    $this.click(function(e){ e.stopPropagation(); });

  6. Ajax json jquery实现菜单案例

    需求: 运用AJAX请求文件menu.json,配置菜单栏,并实现以下功能点: 1. 点击向左箭头,菜单向左移动,隐藏 2. 点击向右箭头,菜单向右移动,显示3. 点击一级菜单,被点击菜单的子菜单显示 ...

  7. [BZOJ 3884][欧拉定理]上帝与集合的正确使用方法

    看看我们机房某畸形写的题解:http://blog.csdn.net/sinat_27410769/article/details/46754209 此题为popoQQQ神犇所出,在此orz #inc ...

  8. Java測试覆盖率工具----Cobertura,EclEmma

    Cobertura 是一个与Junit集成的代码覆盖率測量工具 它是免费.开源的 它能够与Ant和Maven集成.也能够通过命令行调用 能够生成HTML或XML格式的报告 能够依照不同的标准对HTML ...

  9. xml与json格式互转

    最近要整一些报文测试的事情,可当前项目的请求报文格式却不统一,有XML也有JSON,为了一致性,决定统一用JSON格式处理. xmltodict : Makes working with XML fe ...

  10. [Android 性能优化系列]内存之基础篇--Android怎样管理内存

    大家假设喜欢我的博客,请关注一下我的微博,请点击这里(http://weibo.com/kifile),谢谢 转载请标明出处(http://blog.csdn.net/kifile),再次感谢 原文地 ...