php反射机制详解,PHP反射机制

PHP反射机制

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

反射

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

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 \Illuminate\Contracts\Container\BindingResolutionException

*/

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容器的依赖注入的问题。

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值