摘要:本章讲解反射类的使用及对反射的使用。各位很清楚,方法用于解析类,所有方法的实现一定是在引用的文件内。致谢感谢你看到这里,本篇文章源码解析靠个人理解。
前言
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...
inNamespace()); var_dump($function->getName()); var_dump($function->getNamespaceName()); var_dump($function->getShortName()); $function = new ReflectionClass("ABFoo"); 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) "ABFoo" string(3) "AB" 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(IlluminateContractsHttpKernel::class); $response = $kernel->handle( $request = IlluminateHttpRequest::capture() ); $response->send(); $kernel->terminate($request, $response);
是引用语句发生的下一行调用了make方法。各位很清楚,make方法用于解析类,所有make方法的实现一定是在引用的文件内。
bootstrapapp.php$app = new IlluminateFoundationApplication( realpath(__DIR__."/../") );
laravel开始加载它的核心类,所有的实现从 IlluminateFoundationApplication 开始。
IlluminateFoundationApplicationpublic 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,要知道作为独立的模块 “服务容器”是绝对不能写在核心类的。懂点设计模式的都很清楚。
IlluminateContainerContainer以 $api = $this->app->make("HelpSpotAPI",["id"=>1]); 为例来讲解
// 真正的make方法,它直接调用了resolve继续去实现make的功能 // $abstract = "HelpSpotAPI" public function make($abstract, array $parameters = []) { // $abstract = "HelpSpotAPI" return $this->resolve($abstract, $parameters); } ... protected function resolve($abstract, $parameters = []) { ... // 判断是否可以合理反射 // $abstract = "HelpSpotAPI" if ($this->isBuildable($concrete, $abstract)) { // 实例化具体实例 (实际并不是实例化,而是通过反射“解刨”了) $object = $this->build($concrete); } else { $object = $this->make($concrete); } ... } public function build($concrete) { // $concrete = "HelpSpotAPI" 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://www.ucloud.cn/yun/29414.html
摘要:入口启动后,会先加载服务提供者中间件等组件,在查找路由之前因为我们使用的是门面,所以先要查到的实体类。注册第一步当然还是通过服务提供者,因为这是启动的关键,在内加载路由文件。因路由文件中没有命名空间。 showImg(https://segmentfault.com/img/bVbhjvY?w=600&h=296); 前言 我的解析文章并非深层次多领域的解析攻略。但是参考着开发文档看此...
摘要:说明中经常使用的反射特性来设计代码,本文主要学习的反射特性,来提高写代码时的设计质量。提供一套检测的两个工具包和,类似于探针一样的东西来探测这些一等公民。限于篇幅,下篇再聊下反射。 说明:Laravel中经常使用PHP的反射特性来设计代码,本文主要学习PHP的反射特性,来提高写代码时的设计质量。PHP提供一套检测class, interface, trait, property, me...
摘要:判断是否存在构造函数,不存在直接实例化,存在则通过来获取输入函数,并有相应的方法解决依赖参数问题,实现依赖注入。 Laravel 框架关键技术解析·读书笔记(一) 第一章 入口文件 请求访问的入口文件,主要完成几部分工作,分别是: 自动加载函数的添加 服务器实例化与服务注册 路由加载 请求实例化与路由分发 相应生成与发送 其中,自动加载函数用于包含引用文件,改文件是composer...
在 Laravel 的控制器的构造方法或者成员方法,都可以通过类型约束的方式使用依赖注入,如: public function store(Request $request) { //TODO } 这里 $request 参数就使用了类型约束,Request 是类型约束的类型,它是一个类:IlluminateHttpRequest. 本文研究 Laravel 的依赖注入原理,为什么这样定义...
摘要:而函数作用是加载延迟服务,与容器解析关系不大,我们放在以后再说。在构造之前,服务容器会先把放入中,继而再去解析。利用服务容器解析依赖的参数。 make解析 首先欢迎关注我的博客: www.leoyang90.cn 服务容器对对象的自动解析是服务容器的核心功能,make 函数、build 函数是实例化对象重要的核心,先大致看一下代码: public function make($abst...
阅读 1983·2021-11-08 13:14
阅读 2912·2021-10-18 13:34
阅读 1980·2021-09-23 11:21
阅读 3561·2019-08-30 15:54
阅读 1693·2019-08-30 15:54
阅读 2876·2019-08-29 15:33
阅读 2544·2019-08-29 14:01
阅读 1923·2019-08-29 13:52