zeptech/annotations

PHP文档块注解解析

1.2.0 2022-03-19 17:19 UTC

This package is not auto-updated.

Last update: 2024-09-15 04:57:40 UTC


README

这个库提供了对类、方法和成员文档注释中定义的注解的解析。注解以具有数组访问能力的对象的形式提供。

安装

通过Composer安装

{
    "require": {
        "zeptech/annotations": "1.2.0"
    }
}

实例化

要实例化,只需将具有getDocComment()方法的SPL Reflector实例传递给Annotations构造函数。

<?php
use \zpt\anno\Annotations;

$classReflector = new ReflectionClass('MyClass');
$classAnnotations = new Annotations($classReflector);

$methodAnnotations = array();
foreach ($classReflector->getMethods() as $methodReflector) {
    $methodAnnotations[$methodReflector->getName()] = new Annotations($methodReflector);
}

工厂

创建多个具有相同文档注释的Annotation实例的项目,或发现有必要进行大量参数传递以避免这种情况的项目,可能受益于使用AnnotationFactory。AnnotationFactories将根据文档注释的md5哈希值缓存Annotation实例。计算此值通常比多次解析注释要快。

<?php
use \zpt\anno\AnnotationFactory;

$factory = new AnnotationFactory;
$annos = $factory->get('stdclass');

注解语法

所有注解都不区分大小写。所有注解的默认值是true

<?php
/**
 * @Characteristic
 */
class MyClass {
}

$annotations = new Annotations(new ReflectionClass('MyClass'));
$annotations['Characteristic'] === true;

注解的缺失将导致null

$annotations['AnotherCharacteristic'] === null;
isset($annotations['AnotherCharacteristic']) === false;

可以将注解显式设置为具有false的值

<?php
/**
 * @Characteristic false
 */

$annotations['Characteristic'] === false;
isset($annotations['Characteristic']) === true;

可以使用hasAnnotation($annotation)方法确定注解的存在,无论其值如何。

<?php
$annotations->hasAnnotation('Characteristic') === true;
$annotations->hasAnnotation('AnotherCharacteristic') === false;

注解值

单个注解值可以定义为

<?php
/**
 * @LikesToEat cheese
 */
class MyClass {
    // ...
}

$annotations['LikesToEat'] === 'cheese';

某些值将转换为它们的预期类型;字符串'true''false'将转换为它们的布尔等效值,数值将转换为int或float类型。

列表

可以通过提供用方括号括起来的逗号分隔的列表来指定列表值

<?php
/**
 * @LikesToEat [ cheese, kraft dinner, hot dogs ]
 */
// ...

$annotations['LikesToEat'] == array('cheese', 'kraft dinner', 'hot dogs');

解析后的列表值将表示为PHP数组

<?php
is_array($annotations['LikesToEat']) === true

也可以通过定义具有相同名称的多个注解来创建列表

/**
 * @LikesToDrink water
 * @LikesToDrink beer
 */
// ...

$annotations['LikesToDrink'] == array('water', 'beer');

映射

可以使用命名参数指定映射值

<?php
/**
 * @LikesToEat weekend = [ chips, dip ], anytime = [ cheese, kraft dinner, hot dogs ]
 */
// ...

$annotations['likesToEat']['weekend'] == array('chips', 'dip');
$annotations['likesToEat']['anytime'] == array('cheese', 'kraft dinner', 'hot dogs');

嵌套

列表可以嵌套在列表或映射内部。

/**
 * This is a comment which contains an annotation value with a nested list.
 *
 * @ListNest [ [0], [1], [2] ]
 * @MapNest oneZero = [0], oneOne = [1], oneTwo = [2]
 */
// ...

$annotation['listnest'] = array( array(0), array(1), array(2) );
$annotation['mapnest'] = array( 'oneZero' => array(0), 'oneOne' => array(1), 'oneTwo' => array(2) );

目前,这仅支持一级嵌套。不支持深层嵌套。此外,映射不能嵌套。如果需要深层嵌套或嵌套映射,则将指定为JSON对象的值解析为使用json_decode

/**
 * @MenuData {"root":{"child":{"arraychild":[0,1,2,3]}},"arraysroot":[1,2,3]}
 */

由于使用了json_decode,解析的值将是stdClass的实例而不是数组

$annotations['menudata']->root->child->arraychild = array( 0, 1, 2, 3 )

注意:所有注解值都可以用可选的括号包围。

<?php
/**
 * @LikesToEat([ cheese, kraft dinner, hot dogs ])
 * @DoesNotLikeToEat( morning = salad, night = [ toast, fruit ])
 */

奇异性

在多个声明中使用类型混合时可能不会导致错误,但官方不支持,并且可能有一些奇怪的行为。最终结果将取决于使用的类型顺序。

/**
 * @Yolo [ sounds, like, a, good, time ]
 * @Yolo [ but, is, it? ]
 * @Yolo yolo!
 */

值可以放在双引号内,这些引号将被删除,但此功能支持得不好,并且可能不会像预期的那样表现。这可能是将来得到适当处理的事情。

请注意,尽管注解名称不区分大小写,但参数名称区分大小写。这是顶级注解存储在实现自定义访问器的对象中,但映射值存储为本地数组实例的结果。

贡献

开发设置

  1. 本地安装composer

    php -r "copy('https://getcomposer.org.cn/installer', 'composer-setup.php');"
    php -r "if (hash_file('sha384', 'composer-setup.php') === '906a84df04cea2aa72f40b5f787e49f22d4c2f19492ac310e8cba5b96ac8b64115ac402c8cd292b8a03482574915d1a8') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
    php composer-setup.php
    php -r "unlink('composer-setup.php');"
    
  2. 安装依赖项

    php composer.phar update
    
  3. 运行测试

    ./vendor/bin/phpunit test