资讯专栏INFORMATION COLUMN

PHP反射机制

URLOS / 352人阅读

摘要:反射机制反射机制从开始支持,做业务开发的话应该很少接触反射。我的理解就是反射机制能拿到类里面的属性方法,和的也可以以上是官方文档中给出的东西,说实话我看了感觉没什么感觉。在容器成员变量中数组维护这个类,反射实例调用构造函数,获取返回值。

PHP反射机制

PHP反射机制从PHP5开始支持,做业务开发的话应该很少接触反射。我其实也是接触不多,最近在学习laravel的"优雅",就接触了到它其中的反射用法,已经我自己的看法想法。

反射

按照之前的套路,我们来看一下官方手册,官方是怎么说的。

Reflection

PHP 5 具有完整的反射 API,添加了对类、接口、函数、方法和扩展进行反向工程的能力。 此外,反射 API 提供了方法来取出函数、类和方法中的文档注释。我的理解就是php反射机制能拿到类里面的属性方法,private 和 protected的也可以

以上是官方文档中给出的东西,说实话我看了感觉没什么感觉。

能get到的点就是我们能够通过这个窥探一个类所有信息,就像在别人的窗上桶了一个洞一样。

我应该怎么用,或者基于什么场景去用呢?这还是很伤的。

laravel中的反射

laravel整个框架设计的"优雅"就是在于container、IOC、依赖注入。我们来看一下容器中一段关于反射的代码:
IlluminateContainerContainer:

/**
     * Instantiate a concrete instance of the given type.
     *
     * @param  string  $concrete
     * @param  array   $parameters
     * @return mixed
     *
     * @throws IlluminateContractsContainerBindingResolutionException
     */
    public function build($concrete, array $parameters = [])
    {
        // If the concrete type is actually a Closure, we will just execute it and
        // hand back the results of the functions, which allows functions to be
        // used as resolvers for more fine-tuned resolution of these objects.
        if ($concrete instanceof Closure) {
            return $concrete($this, $parameters);
        }

        $reflector = new ReflectionClass($concrete);

        // If the type is not instantiable, the developer is attempting to resolve
        // an abstract type such as an Interface of Abstract Class and there is
        // no binding registered for the abstractions so we need to bail out.
        if (! $reflector->isInstantiable()) {
            if (! empty($this->buildStack)) {
                $previous = implode(", ", $this->buildStack);

                $message = "Target [$concrete] is not instantiable while building [$previous].";
            } else {
                $message = "Target [$concrete] is not instantiable.";
            }

            throw new BindingResolutionException($message);
        }

        $this->buildStack[] = $concrete;

        $constructor = $reflector->getConstructor();

        // If there are no constructors, that means there are no dependencies then
        // we can just resolve the instances of the objects right away, without
        // resolving any other types or dependencies out of these containers.
        if (is_null($constructor)) {
            array_pop($this->buildStack);

            return new $concrete;
        }

        $dependencies = $constructor->getParameters();

        // Once we have all the constructor"s parameters we can create each of the
        // dependency instances and then use the reflection instances to make a
        // new instance of this class, injecting the created dependencies in.
        $parameters = $this->keyParametersByArgument(
            $dependencies, $parameters
        );

        $instances = $this->getDependencies(
            $dependencies, $parameters
        );

        array_pop($this->buildStack);

        return $reflector->newInstanceArgs($instances);
    }
    

就是实现绑定类的方法,build方法。下面我们就来分析一下:

参数:$concreate string 类似于Model::class这种嘛,不难理解。$parameters array 参数 更不难理解了吧。

判断 $concreate 是否是匿名类(闭包),是匿名类就执行这个函数.

创建反射类,去映射这个类。

判断这个类能否被实例化,也就是看构造函数是否是private。否就抛出出异常。

在容器成员变量中数组维护这个类,反射实例调用构造函数,获取返回值。

判断返回值是否为空,如果为空就说明不需要参数依赖,那么就直接实例化。否则就获取构造函数的参数依赖,将传入的参数和依赖参数进行对照。

最后,在调用newInstanceArgs进行实例化,之后返回实例。

后记

其实在上面这个laravel中的例子已经很好的阐明了反射机制的使用方式,或许你现在的业务场景还未必能够使用到这种机制。但是,当碰到的时候请记得还有这种方式能够使用。

当你需要去实例化一个类,但是这个类对你来说完全就是封闭或者说是未知的,你可以创建反射来与映射这个类,通过一系列的探测来最终实例化这个类,尤其还在动态运行中的。

基于这种机制,其实可以玩出很多的花样。比如说能够自动生成文档。

实现MVC这种架构,使用反射自动调用实现

$class = new ReflectionClass(ucfirst($controller));
$controller = $class->newInstance();
if ($class->hasMethod($method)) {
    $method = $class->getMethod($method);
    $method->invokeArgs($controller, $arguments);
} else {
    throw new Exception("{$controller} controller method {$method} not exists!");
}

实现单元测试

    $class = new ReflectionClass($class);
    if ($class->hasMethod($method)) {
        $method = $class->getMethod($method);
        $object = $class->newInstance();
        $class = $method->invokeArgs(new $object, $params);
        var_dump($res === $assert);
    }

laravel中的反射帮助它解决DI容器的依赖注入的问题。

还有很多好玩的等着你自己去尝试,这种机制究竟能玩出多少花样,就看你自己怎么玩了。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/25751.html

相关文章

  • php 反射机制查看

    1.查看类属性以及方法 single.php class single { private static $instance; public function __construct() {} /**@return single */ public static function getInstance() { if(!isset(self::$i...

    用户84 评论0 收藏0
  • PHP高级特性-反射Reflection以及Factory工厂设计模式的结合使用[代码实例]

    摘要:反射提供给面向对象编程可以自省的能力,即反射。在简单工厂模式中,根据传递的参数来返回不同的类的实例简单工厂模式又称为静态工厂方法模式。也就是简单工厂模式工厂工厂类。PHP高级特性-反射以及工厂设计模式的结合使用 [结合 Laravel-Admin 代码实例讲解]利用反射来实现工厂模式的生产而无需创建特定的工厂类本文地址http://janrs.com/?p=833转载无需经过作者本人授权转载...

    番茄西红柿 评论0 收藏2637
  • 【Laravel】Laravel 框架关键技术解析·读书笔记(一)

    摘要:判断是否存在构造函数,不存在直接实例化,存在则通过来获取输入函数,并有相应的方法解决依赖参数问题,实现依赖注入。 Laravel 框架关键技术解析·读书笔记(一) 第一章 入口文件 请求访问的入口文件,主要完成几部分工作,分别是: 自动加载函数的添加 服务器实例化与服务注册 路由加载 请求实例化与路由分发 相应生成与发送 其中,自动加载函数用于包含引用文件,改文件是composer...

    CocoaChina 评论0 收藏0
  • 【modernPHP专题(2)】反射机制Reflection

    摘要:简介是才有的新功能,它是用来导出或提取出关于类方法属性参数等的详细信息,包括注释。 简介 PHP Reflection API是PHP5才有的新功能,它是用来导出或提取出关于类、方法、属性、参数等的详细信息,包括注释。 class Reflection { } interface Reflector { } class ReflectionException extends Exce...

    mrli2016 评论0 收藏0
  • PHP通过反射来得到类,以及一些基本的应用

    摘要:发现大量的使用了反射机制。下面就来简单看看一些反射的应用获得反射下面我们来通过这个反射来得到的私有属性得到结果得到这样我们就可以很轻松的获得的私有属性了。最后通过执行该方法反射还有很多可用的方法,这里就不一一说了。 这几天在看laravel框架的核心代码。发现大量的使用了反射机制。下面就来简单看看一些反射的应用 class A { private $_foo = this i...

    BlackHole1 评论0 收藏0

发表评论

0条评论

URLOS

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<