its-mieger/annotations

Laravel 的 PHP 注解

1.4.1 2018-05-09 12:22 UTC

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返回每个类型的唯一注解,因为相同类型的注解会互相覆盖。这遵循以下规则:

  • 文档注释中的较后注解覆盖之前的注解。
  • 类注解覆盖父类注解。
  • 接口注解覆盖类注解。
  • 扩展接口注解覆盖扩展接口注解。