doctrine/annotation 的简单使用
Doctrine注释提供了为PHP类实现自定义注释功能的功能(这里使用的是v1.6版本)。
composer require doctrine/annotations
官方链接:https://www.doctrine-project.org/projects/doctrine-annotations/en/1.6/index.html#introduction
使用大概步骤:
- 定一个注释模板文件
- 在类文件中使用注释(可以看做是给模板赋值)
- 读取注释
使用示例: https://www.cnblogs.com/cshaptx4869/p/12178960.html
# Route.php (定义一个注解模板)
<?php namespace Util\Annotation; use Doctrine\Common\Annotations\Annotation\Attributes;
//use Doctrine\Common\Annotations\Annotation\Enum;
//use Doctrine\Common\Annotations\Annotation\Required; /**
* 创建一个注释类
*
* Annotation表示该类是一个注解类
* Target表示注解生效的范围(ALL,CLASS,METHOD,PROPERTY,ANNOTATION)
*
* @Annotation
* @Target({"METHOD"})
* 也可以在这里变量声明类型
* @Attributes({
* @Attribute("time", type = "int")
* })
*/
final class Route
{
/**
* @Required()
* @var string
*/
public $route; /**
* @Enum({"POST", "GET", "PUT", "DELETE"})
* @var string
*/
public $method; /**
* @var array
*/
public $param; public $time; public function say()
{
echo 'hello';
}
}
# run.php (使用、读取)
<?php require 'vendor/autoload.php'; use Util\Annotation\Route;
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\FileCacheReader;
use Doctrine\Common\Annotations\AnnotationRegistry; /**
* Class UserController
* 模拟在User控制其中定义注解路由
* @author 银酱
*/
class UserController
{
/**
* 列表
* @Route(route="/user/index",method="GET")
*/
public function index()
{
echo __METHOD__;
} /**
* 注册
* @Route(route="/user/register",method="POST",param={"token","access"},time=123)
*/
public function register()
{
echo __METHOD__;
} /**
* 显示
* @Route(route="/user/info",method="POST")
*/
public function info()
{
echo __METHOD__;
} /**
* 更新
* @Route(route="/user/update",method="POST")
*/
public function update()
{ } /**
* 删除
* @Route(route="/user/info",method="DELETE")
*/
public function delete()
{
echo __METHOD__;
}
} //echo '<pre>'; // 注释使用自己的自动加载机制来确定给定的注释是否具有可以自动加载的对应PHP类
// 配置注释自动加载(2.0版本中已剔除)
AnnotationRegistry::registerLoader('class_exists'); //回调需返回true
//AnnotationRegistry::registerFile(__DIR__ . '/Util/Annotation/Route.php'); //注册文件
//AnnotationRegistry::registerAutoloadNamespace('Util\Annotation'); //注册命名空间
//AnnotationRegistry::registerAutoloadNamespaces(['Util\\Annotation' => null]); //注册多个命名空间 // 系统默认 var、author 标记不会识别
$whitelist = [
"after", "afterClass", "backupGlobals", "backupStaticAttributes", "before", "beforeClass", "codeCoverageIgnore*",
"covers", "coversDefaultClass", "coversNothing", "dataProvider", "depends", "doesNotPerformAssertions",
"expectedException", "expectedExceptionCode", "expectedExceptionMessage", "expectedExceptionMessageRegExp", "group",
"large", "medium", "preserveGlobalState", "requires", "runTestsInSeparateProcesses", "runInSeparateProcess", "small",
"test", "testdox", "testWith", "ticket", "uses"
];
foreach ($whitelist as $v) {
AnnotationReader::addGlobalIgnoredName($v);
} $reflectionClass = new \ReflectionClass(UserController::class);
$methods = $reflectionClass->getMethods(); //$reader = new AnnotationReader();
//缓存 reader, 开启debug 若有修改则会更新,否则需手动删除然后更新
$reader = new FileCacheReader(new AnnotationReader(), "runtime/annotation", true); foreach ($methods as $method) {
// 读取Route的注解
$routeAnnotation = $reader->getMethodAnnotation($method, Route::class);
echo '========================' . PHP_EOL;
echo "route: {$routeAnnotation->route}" . PHP_EOL . PHP_EOL;
echo "method: {$routeAnnotation->method}" . PHP_EOL;
$param = print_r($routeAnnotation->param, true);
echo "param: {$param}" . PHP_EOL;
$routeAnnotations[] = $routeAnnotation;
} //var_dump($routeAnnotations);
# 其余实例1
<?php
// 错误处理机制
register_shutdown_function('myShutDown');
set_error_handler('myError');
set_exception_handler('myException'); // require自动加载文件
require 'vendor/autoload.php'; // 该类是一个辅助类,几个属性$value $type $desc将用于描述其他类的属性、方法或者对象的。
/**
* @Annotation
* @Target({"ALL"})
*/
class AnnotatedDescription
{
/**
* @var mixed
*/
public $value; /**
* @var string
*/
public $type; /**
* @var string
*/
public $desc;
} /**
* @AnnotatedDescription("这是一个用于展示Annotation类的例子。")
*/
class AnnotationDemo
{
/**
* @AnnotatedDescription(desc="这个属性必须要为String",type="String")
* @var String
*/
private $property = "I am a private property!"; /**
* @AnnotatedDescription(value="啦啦")
* @var string
*/
protected $extra; /**
* @AnnotatedDescription(desc="不需要传入参数", type="getter")
*/
public function getProperty()
{
return $this->property;
}
} echo "<pre>";
// Lets parse the annotations
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\FileCacheReader; // 缓存到文件
//$annotationReader = new FileCacheReader(new AnnotationReader(), './cache/annotation', true);
$annotationReader = new AnnotationReader(); // Get class annotation
$reflectionClass = new ReflectionClass(AnnotationDemo::class);
// public function getClassAnnotations(\ReflectionClass $class); 访问类的所有注释
$classAnnotations = $annotationReader->getClassAnnotations($reflectionClass);
echo "========= CLASS ANNOTATIONS =========" . PHP_EOL;
print_r($classAnnotations); $annotationDemoObject = new AnnotationDemo();
$reflectionObject = new ReflectionObject($annotationDemoObject);
$objectAnnotations = $annotationReader->getClassAnnotations($reflectionObject);
echo "========= OBJECT ANNOTATIONS =========" . PHP_EOL;
print_r($objectAnnotations); $reflectionProperty = new ReflectionProperty(AnnotationDemo::class, 'property');
// public function getPropertyAnnotations(\ReflectionProperty $property); 访问属性的所有注释
$propertyAnnotations = $annotationReader->getPropertyAnnotations($reflectionProperty);
echo "========= PROPERTY ANNOTATIONS =========" . PHP_EOL;
print_r($propertyAnnotations); $reflectionMethod = new ReflectionMethod(AnnotationDemo::class, 'getProperty');
// public function getMethodAnnotations(\ReflectionMethod $method); 访问方法的所有注释
$methodAnnotations = $annotationReader->getMethodAnnotations($reflectionMethod);
echo "========= Method ANNOTATIONS =========" . PHP_EOL;
print_r($methodAnnotations); function myException($e)
{
var_dump('<h3 style="color:red;">myException:'.$e->getMessage().'</h3>');
} function myError($code, $msg, $file, $line)
{
var_dump(compact('code', 'msg', 'file', 'line'));
} function myShutDown()
{
$data = error_get_last();
if(is_null($data)){
var_dump('nothing error');
} else {
var_dump('error',$data);
}
}
# 其余实例2
<?php set_exception_handler('my_exception'); require_once 'vendor/autoload.php'; use Doctrine\Common\Annotations\AnnotationReader; /**
* 如果您想定义自己的注释,只需将它们分组到一个名称空间中,并在AnnotationRegistry中注册这个名称空间
* 注释类必须包含带有文本的类级docblock Annotation
* @Annotation
*
* 表明注释类型适用于的类元素的类型,即注入注释允许的范围
* 可选值 CLASS,PROPERTY,METHOD,ALL,ANNOTATION ,可选一个或者多个
* 如果在当前上下文中不允许注释,则会得到一个AnnotationException
* @Target({"METHOD","PROPERTY","CLASS"})
*
* 修饰属性
* @Attributes({
* @Attribute("func", type="string"),
* })
*/
class A
{
public $value; /**
* @var string
*/
public $name; /**
* 注释解析器使用phpdoc注释 var 或 Attributes and Attribute 的组合,检查给定的参数
* 可选值 mixed,boolean,bool,float,string,integer,array,SomeAnnotationClass,array<integer>,array<SomeAnnotationClass>
* 如果数据类型不匹配,则会得到一个AnnotationException
* @var integer
*/
public $age; /**
* @var array
*/
public $sex; public $func; /**
* 定义为字段必填,否则报AnnotationException异常
* @Required
*
* 限制可选值,出错报AnnotationException异常
* @Enum({"NORTH", "SOUTH", "EAST", "WEST"})
*/
public $option; // 如果存在构造函数存在参数,则会把组值传给这个参数;反之,如果没有构造函数,则直接将值注入到公共属性
public function __construct()
{
}
} /**
* @A("类注释")
*/
class B
{
/**
* 属性注释
* @A(name="tom",age=18,sex={"male","fmale","secret"},option="NORTH")
*/
public $param; /**
* 方法注释
* @A(func="say")
*/
public function say()
{ }
} $reflection = new ReflectionClass(B::class);
$reader = new AnnotationReader(); // 返回的是对象
$AClassAnnotation = $reader->getPropertyAnnotation($reflection->getProperty('param'), A::class);
// 返回的是对象组成的数组
//$AClassAnnotation = $reader->getPropertyAnnotations($reflection->getProperty('param')); //$AClassAnnotation = $reader->getMethodAnnotation($reflection->getMethod('say'), A::class); //$AClassAnnotation = $reader->getClassAnnotation($reflection, A::class); dump($AClassAnnotation); function my_exception($exception)
{
echo '<div class="alert alert-danger">';
echo '<b>Fatal error</b>: Uncaught exception \'' . get_class($exception) . '\' with message ';
echo $exception->getMessage() . '<br>';
echo 'Stack trace:<pre>' . $exception->getTraceAsString() . '</pre>';
echo 'thrown in <b>' . $exception->getFile() . '</b> on line <b>' . $exception->getLine() . '</b><br>';
echo '</div>';
exit();
} function dump($data)
{
echo '<pre>';
var_dump($data);
exit();
}
# 其他事项:
// 注释使用自己的自动加载机制来确定给定的注释是否具有可以自动加载的对应PHP类
// 配置注释自动加载3种方式(2.0中已删除)
AnnotationRegistry::registerLoader('class_exists'); //回调需返回true //AnnotationRegistry::registerFile(__DIR__ . '/Util/Annotation/Route.php'); //注册文件
//AnnotationRegistry::registerAutoloadNamespace('Util\Annotation'); //注册命名空间 //AnnotationRegistry::registerAutoloadNamespaces(['Util\\Annotation' => null]); //注册多个命名空间
// 添加标签白名单 系统默认去除author 和 var
$whitelist = ["author", "after", "afterClass", "backupGlobals", "backupStaticAttributes", "before", "beforeClass", "codeCoverageIgnore*", "covers", "coversDefaultClass", "coversNothing", "dataProvider", "depends", "doesNotPerformAssertions", "expectedException", "expectedExceptionCode", "expectedExceptionMessage", "expectedExceptionMessageRegExp", "group", "large", "medium", "preserveGlobalState", "requires", "runTestsInSeparateProcesses", "runInSeparateProcess", "small", "test", "testdox", "testWith", "ticket", "uses"];
foreach ($whitelist as $v) {
AnnotationReader::addGlobalIgnoredName($v);
}
# API:
Access all annotations of a class
public function getClassAnnotations(\ReflectionClass $class);
Access one annotation of a class
public function getClassAnnotation(\ReflectionClass $class, $annotationName);
Access all annotations of a method
public function getMethodAnnotations(\ReflectionMethod $method);
Access one annotation of a method
public function getMethodAnnotation(\ReflectionMethod $method, $annotationName);
Access all annotations of a property
public function getPropertyAnnotations(\ReflectionProperty $property);
Access one annotation of a property
public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName);
doctrine/annotation 的简单使用的更多相关文章
- 菜鸟学习Spring——60s使用annotation实现简单AOP
一.概述. AOP大家都知道切面编程,在Spring中annotation可以实现简单的AOP列子.下面还未大家介绍几个概念: Aspect 对横切性关注点的模块化. Advice 对横切性关注点的具 ...
- Spring基于 Annotation 的简单介绍
tyle="margin:20px 0px 0px; font-size:14px; line-height:26px; font-family:Arial"> 1.使用 @ ...
- annotation注释简单介绍
元数据的作用 如果要对于元数据的作用进行分类,目前还没有明确的定义,不过我们可以根据它所起的作用,大致可分为三类: l 编写文档:通过代码里标识的元数据生成文档. l ...
- 菜鸟学习Spring——60s配置XML方法实现简单AOP
一.概述. 上一篇博客讲述了用注解的形式实现AOP现在讲述另外一种AOP实现的方式利用XML来实现AOP. 二.代码演示. 准备工作参照上一篇博客<菜鸟学习Spring--60s使用annota ...
- Annotation(jdk5.0注解)复习(转自http://3w_cnblogs_com/pepcod/)
package annotation.test; import java.lang.annotation.ElementType; import java.lang.annotation.Retent ...
- Java Annotation手册
Java Annotation手册 作者:cleverpig(作者的Blog:http://blog.matrix.org.cn/page/cleverpig) 原文:http://www.matri ...
- Annotation注解
概述 Annotation是JDK 5.0以后提供对元数据的支持,可以在编译.加载和运行时被读取,并执行相应的处理.所谓Annotation就是提供了一种为程序元素设置元数据的方法,可用于修饰包.类. ...
- VS简单注释插件——VS插件开发续
VS简单注释插件——VS插件开发续 前些时候,我写过一篇<VS版权信息插件——初试VS插件开发小记>分享过一个用于添加注释信息的插件,但那个插件有几个问题: 不能添加带块注释(/**/), ...
- Hibernate---第一个helloworld程序 (XML版本, annotation版本)
Hibernate作为JPA的一种实现,jpa的注解已经是hibernate的核心,hibernate只提供了一些补充,而不是两套注解.hibernate对jpa的支持够足量,在使用hibernate ...
随机推荐
- spark-sql中的DataFrame文件格式转储示例
SparkConf sparkConf = new SparkConf() // .setMaster("local") .setAppName("DataFrameTe ...
- 谈谈那些年我们装B的并发编程
谈谈那些年我们装B的并发编程 每个人对并发编程的理解会有差异,但是终极目标始终是追求尽可能高的处理性能.那么如何尽可能的提升处理性能呢? 我们可以从单核,多核,并发,并行的基础出发.首先,介绍下基础知 ...
- java框架之Hibernate(4)-几种检索方式
准备 模型及映射文件 package com.zze.bean; import java.util.HashSet; import java.util.Set; public class Class ...
- python进阶之 网络编程
1.tcp和udp协议的区别 TCP协议 面向连接\可靠\慢\对传递的数据的长短没有要求 两台机器之间要想传递信息必须先建立连接 之后在有了连接的基础上,进行信息的传递 可靠 : 数据不会丢失 不会重 ...
- JavaScript 常用数组函数方法专题
1. 由字符串生成数组 split() 分割字符串,并将分割的部分作为一个元素保存在一个新建的数组中. var str1 = "this is an emample to using the ...
- C# Tuple<T1,T2....T>元组的使用
1) 先说组元:一个数据结构,由通过逗号分割的,用于传递给一个程序或者操作系统的一系列值的组合. NET Framework 直接支持一至七元素的元组 Tuple<T1> Tuple< ...
- Python使用中错误(持续更新.....)
1.在使用requests发送请求,响应数据转成json提示,没有可解码的json 解决办法: 这是由于,发送请求的数据,存在错误,响应出错比如404 400,所以找不到可以解码的json 示例如下: ...
- noip2016海港
题目描述 Description 小K是一个海港的海关工作人员,每天都有许多船只到达海港,船上通常有很多来自不同国家的乘客. 小K对这些到达海港的船只非常感兴趣,他按照时间记录下了到达海港的每一艘船只 ...
- 【2017-05-02】winform弹出警告框选择性操作、记事本制作、对话框控件和输入输出流
一.winform弹出警告框选择性操作 MessageBox.Show()返回一个枚举类值(第一个参数为弹出窗口显示的内容,第二个参数为弹出窗口的标题,第三个参数为弹出窗口包含的按钮) 先新建一个变量 ...
- PriorityBlockingQueue 原理分析
PriorityBlockingQueue是一个支持优先级的无界阻塞队列,直到系统资源耗尽.默认情况下元素采用自然顺序升序排列.也可以自定义类实现compareTo()方法来指定元素排序规则,或者初始 ...