赞
踩
对于开发java的同学来说注解是一种再熟悉不过的东西了,在代码中一般无处不见注解的存在。php对于注解并没有原生支持,但是有人做了公共包可以来使用。
那注解是什么,简单来说注解是给程序扩展用的,当程序运行的注解会被解析到源代码中,他的声明有点像注释,注释是给程序员看的用来了解、熟悉某个类或者方法的具体用途、参数、属性等等。而注解则会告诉程序,执行到这里的时候需要如何去做。
先来看一下hyperf中的简单使用
<?phpuse HyperfHttpServerAnnotationController;use HyperfHttpServerAnnotationGetMapping;/** * Class IndexController * @package AppController * //声明这是一个控制器注解,其实Controller也是一个类,prefix是它的 // 一个属性,这声明了这个控制器的访问路由,api/v1/test * @Controller(prefix="api/v1/test") */class IndexController extends AbstractController{ /** * @return array // GetMapping 用来说明这是个get请求方法 ,path代表路径 * @GetMapping(path="index") */ public function index() { $user = $this->request->input('user', 'Hyperf'); $method = $this->request->getMethod(); return [ 'method' => $method, 'message' => "Hello {$user}.", ]; }}
我们启动服务之后直接访问 127.0.0.1:9501/api/v1/test/index 就可以
在如Laravel的框架中,我们会将路由配置在Router.php中,请求进来后会匹配文件中的路由,其实与这里的原理是差不多的,当然注解的功能要强大的多一些。
先看注解的声明
vendor/hyperf/http-server/src/Annotation/Controller.php
<?phpuse HyperfDiAnnotationAbstractAnnotation;/** 必须使用Annotation声明这是一个注解类 * @Annotation target标识这个注解的使用范围,可以作用的一个类上,不能用在func上 * @Target({"CLASS"}) */class Controller extends AbstractAnnotation{ /** * @var null|string 这个属性代表,我们在使用的时候必须要传入这个值 */ public $prefix = ''; /** * @var string */ public $server = 'http';}
我们说server启动的时候会先扫描注解,并且解析,具体看ClassLoader方法,扫描后的注解会被放到container中,按照类对应的方法的注解等等。
当请求进来的时候会解析这个数据,如果是Controller或者Mapping的注解,会被解析到Router里面,绑定url对应的class及func,这样就可以匹配到了。也就是[api/v1/test] => [IndexController, index]。
其他的注解也是这样的流程,只不过是作用不同而已,我们也可以自定义注解。
大家可以看下这个包,目前PHP所实现的注解都是基于这个,https://www.doctrine-project.org/projects/doctrine-annotations/en/latest/index.html, 其根本原理是利用反射,Reflection来实现,我们来个例子
reflection/index.php
<?phprequire __DIR__."/../vendor/autoload.php";/** * Class Phone * * @MyControllerAnnotion( * * prefix="v1/api" * ) * */class Phone{ public $version; public function call() { echo "is calling..."; }}/** * 假设是个自定义的注解类 * Class MyControllerAnnotion * * @Annotation */class MyControllerAnnotion{ public $prefix;}$class = new ReflectionClass(Phone::class);// 第一步获取这个类的注释$comment = $class->getDocComment();print_r($comment);// 第二部就要把这个注释中的注解解析出来了,主要是正则匹配啥的了// 这个还真是有点复杂,我们使用人家的包来解析$reader = new DoctrineCommonAnnotationsAnnotationReader();$annitons = $reader->getClassAnnotation($class, MyControllerAnnotion::class);print_r($annitons);// 第三部摘出来注解之后,跟当前类进行关联就行了,啥时候用取出来就可以了$container[$class->getName()]['class'][] = $annitons;print_r($container);// 第四部就是使用了,无非就是初始化注解,获取他的属性啥的
来看下结果
gaoz@nobodyMBP hyperf_study % php hyperf-skeleton/reflection/index.php/** * Class Phone * * @MyControllerAnnotion( * * prefix="v1/api" * ) * */MyControllerAnnotion Object( [prefix] => v1/api)Array( [Phone] => Array ( [class] => Array ( [0] => MyControllerAnnotion Object ( [prefix] => v1/api ) ) ))
目前看来这个东西真是大大提高效率,java的同学应该很有体会,通过注解,可以帮我们做很多准备工作,很可惜PHP的社区一直没有出这个玩意
相关文档:
hypef中对于注解的说明:https://hyperf.wiki/2.0/#/zh-cn/annotation
注解解析工具:https://github.com/doctrine/annotations
相关代码:
https://github.com/nobody05/hyperf_study
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。