its-mieger / annotations
Laravel 的 PHP 注解
Requires
- php: ^7.1
Requires (Dev)
- nette/php-generator: ^3.1
- orchestra/testbench: ^3.5
- phpunit/phpunit: 6.5.5
This package is auto-updated.
Last update: 2024-09-22 03:36:27 UTC
README
这个库允许轻松实现和使用 Laravel 项目的注解。与其他许多注解库不同,它支持注解的继承。
安装
如果不使用包自动发现,您必须将服务提供程序添加到 config/app.php 中的 providers 数组中
ItsMieger\Annotations\Provider\AnnotationsServiceProvider::class,
此外,请记住注册 Events 服务提供程序。这允许在清除其他缓存时清除注解缓存。
##注解
@Annotation
@Annotation arg1 arg2
@Annotation(arg1, arg2)
@Annotation(arg1, "argument 2")
@Annotation(arg1=7, arg2=8)
@Annotation(
arg1,
arg2
)
// JSON
@Annotation(arg1, {"x": 15})
@Annotation(arg1, [1, 5, 17])
@Annotation(arg1, (true))
前两个注解演示了简单的注解语法。参数通过空格分隔。
然而,有时注解需要更复杂的参数。因此,您可以使用扩展语法,该语法由注解名称后面的开括号 直接 标识。这允许您使用引号、指定参数键或使用多行来注解。
您甚至可以使用 JSON 作为参数,如最后三个示例所示。JSON 表达式由 "{" (关联数组),"[" (简单数组) 和 "(" (简单表达式) 包围。
使用 \
(反斜杠) 转义具有特殊意义的字符,例如:"quote \" in text"
。
创建注解
实现自定义注解非常简单。只需扩展 AbstractAnnotation
类
namespace Test\Name\Space
class MyAnnotation extends AbstractAnnotation
{
/**
* @inheritDoc
*/
public function __construct(array $parameters) {
parent::__construct($parameters);
/* ... */
}
}
所有解析的参数都作为 (关联) 数组传递给注解的构造函数。请记住调用父构造函数,这样所有其他方法都能按预期工作。
要使用上述注解,您必须在文档注释中使用完全限定的类名
/**
* @Test\Name\Space\MyAnnotation
*/
短注解名称
由于使用完全限定名称会使代码难以阅读,因此您可以注册注解的短名称
Annotations::register(MyAnnotation::class, 'myAnnotation');
这允许您按如下方式使用您的注解
/**
* @myAnnotation
*/
当然,仍然可以使用完全限定名称。
读取注解
可以使用 AnnotationReader
外观读取注解
AnnotationReader::getClassAnnotations($cls, $filters = []);
这返回了为给定类定义的所有注解。您可以传递一个类名、一个实例或一个反射类。第二个参数允许您传递要返回的注解列表。每个元素可以是注解类名称或注解的已注册短名称。如果省略,则返回所有找到的注解。如果找到多个相同的注解,则返回多个相同的注解。
如果您只对单个注解感兴趣,则 getClassAnnotation
方法是您需要的
AnnotationReader::getClassAnnotation($cls, $annotationName)
第二个参数是注解类名称或已注册的短名称。它返回找到的最后一个匹配注解或 null
如果不存在。
泛型注解
没有找到类的注解返回为 GenericAnnotation
。这些注解通过 getName
返回注解名称,并通过其 getParameters
方法返回所有注解参数
/**
* @UnlinkedAnnotation(arg1, arg2)
*/
$annotation->getName();
// "UnlinkedAnnotation"
$annotation->getParameters():
// ["arg1", "arg2"]
要过滤泛型注解,请在注解名称前加上 "generic:"
AnnotationReader::getClassAnnotation($cls, "generic:UnlinkedAnnotation")
缓存
解析注解会影响程序性能。因此,使用缓存,以便注解不必在每次调用时解析。这意味着如果您修改了影响注解的源代码的一部分,则必须清除注解缓存。如果您通过 artisan cache:clear
清除应用程序缓存,则也会清除注解缓存。如果您只想清除注解缓存,请使用 artisan annotations:clear
。
默认情况下,PHP缓存驱动用于注解。这是一个生产环境下的优秀选择,因为它可能从PHP字节码缓存中受益。然而,对于开发或测试,此缓存可能难以使用,因为你需要反复清除它。
因此,您可能可以使用内存缓存驱动来处理这些环境,该驱动只缓存请求生命周期的注解。您可以通过ANNOTATION_CACHE
环境变量更改使用的缓存。
ANNOTATION_CACHE=memory
忽略的注解
PHP存在许多仅用于文档或其他目的的注解。默认情况下,这些注解被忽略以提高性能和缓存大小。但是,可以使用ignore
选项配置列表。
另一种方法是显式注册一个类以忽略某个注解,这样它就不再被忽略了。
Annotations::register(MyVarAnnotation::class, 'var');
注解继承
与其他注解库的主要区别之一是支持继承注解。这允许接口或父类定义注解,这些注解将由实现类继承。
interface A {
/**
* @InterfaceAnnotation
* @OverriddenAnnotation(fromInterface)
*/
public function getValue();
}
class B implements A {
/**
* @ClassAnnotation
* @OverriddenAnnotation(fromClass)
*/
public function getValue();
}
使用InheritedAnnotationReader
读取时,也考虑继承的注解。
$annotations = InheritedAnnotationReader::getMethodAnnotations('B', 'getValue');
// @InterfaceAnnotation
// @ClassAnnotation
// @OverriddenAnnotation(fromInterface)
如您所见,接口注解被添加到类注解中。实际上,它们也覆盖了同类型的类注解。
InheritedAnnotationReader
返回每个类型的唯一注解,因为相同类型的注解会互相覆盖。这遵循以下规则:
- 文档注释中的较后注解覆盖之前的注解。
- 类注解覆盖父类注解。
- 接口注解覆盖类注解。
- 扩展接口注解覆盖扩展接口注解。