egorov/yii2-annotations

允许你在Yii2项目中使用doctrine/annotations

1.1.0 2020-09-12 09:29 UTC

This package is auto-updated.

Last update: 2024-09-16 00:33:31 UTC


README

Yii2 Annotations 扩展

主分支: Scrutinizer Code Quality Code Coverage Build Status

开发分支: Scrutinizer Code Quality Code Coverage Build Status

使用Yii2缓存驱动程序在Yii2项目中使用 doctrine/annotations

安装

composer require egorov/yii2-annotations

配置

...
    'components' => [
        'annotations' => [
            'class' => 'yii\annotations\Annotations',
            'cache' => '\yii\caching\FileCache',
            'path' => '@runtime/annotations',
            'debug' => false,
            'ignoreAnnotations' => [
                'properties', 'relations', 'property'
            ]
        ]
    ],
...

其中

class - yii\annotations\Annotations class or class implementing yii\annotations\AnnotationsInterface,
cache - Optional. Container with cache component defined in configuration or cache class. By default 'cache',
path -  Optional. Annotations cache dir for \yii\caching\FileCache,
debug - Optional boolean. Debug enable. True means that the cache will be invalid every time the file is changed, false - the cache will be generated once
ignoreAnnotations - List of ignored annotations when parsing a file

注解类

注解类必须包含包含文本 @Annotation 的类级别 docblock

/** @Annotation */
class Bar
{
    // some code
}

注入注解值

注解解析器检查注解构造函数是否有参数,如果有,则传递值数组,否则将尝试直接将值注入到公共属性中

/**
 * @Annotation
 *
 * Some Annotation using a constructor
 */
class Bar
{
    private $foo;

    public function __construct(array $values)
    {
        $this->foo = $values['foo'];
    }
}

/**
 * @Annotation
 *
 * Some Annotation without a constructor
 */
class Foo
{
    public $bar;
}

注解目标

@Target 表示注解类型适用于哪些类元素的类型。然后你可以定义一个或多个目标

CLASS 在类 docblock 中允许 PROPERTY 在属性 docblock 中允许 METHOD 在方法 docblock 中允许 ALL 在类、属性和方法 docblock 中允许 ANNOTATION 在其他注解内部允许 如果注解不允许在当前上下文中,您将收到 AnnotationException

/**
 * @Annotation
 * @Target({"METHOD","PROPERTY"})
 */
class Bar
{
    // some code
}

/**
 * @Annotation
 * @Target("CLASS")
 */
class Foo
{
    // some code
}

属性类型

注解解析器使用 phpdoc 注释 @var 检查给定的参数,数据类型可以使用注解属性上的 @var 注释或使用 @Attributes 和 @Attribute 注解进行验证

如果数据类型不匹配,您将收到 AnnotationException

/**
 * @Annotation
 * @Target({"METHOD","PROPERTY"})
 */
class Bar
{
    /** @var mixed */
    public $mixed;

    /** @var boolean */
    public $boolean;

    /** @var bool */
    public $bool;

    /** @var float */
    public $float;

    /** @var string */
    public $string;

    /** @var integer */
    public $integer;

    /** @var array */
    public $array;

    /** @var SomeAnnotationClass */
    public $annotation;

    /** @var array<integer> */
    public $arrayOfIntegers;

    /** @var array<SomeAnnotationClass> */
    public $arrayOfAnnotations;
}

/**
 * @Annotation
 * @Target({"METHOD","PROPERTY"})
 * @Attributes({
 *   @Attribute("stringProperty", type = "string"),
 *   @Attribute("annotProperty",  type = "SomeAnnotationClass"),
 * })
 */
class Foo
{
    public function __construct(array $values)
    {
        $this->stringProperty = $values['stringProperty'];
        $this->annotProperty = $values['annotProperty'];
    }

    // some code
}

注解必需

@Required 表示当使用注解时必须指定字段。如果没有使用,则获取 AnnotationException,指出此值不能为空。

声明必需字段

/**
 * @Annotation
 * @Target("ALL")
 */
class Foo
{
    /** @Required */
    public $requiredField;
}

用法


/** @Foo(requiredField="value") */
public $direction;                  // Valid

 /** @Foo */
public $direction;                  // Required field missing, throws an AnnotationException

枚举值

带有 @Enum 标记的注解属性是一个接受固定标量值集合的字段。您应该在任何需要表示固定值的情况下使用 @Enum 字段。注解解析器检查给定的值,并在值不匹配时抛出 AnnotationException。声明枚举属性

/**
 * @Annotation
 * @Target("ALL")
 */
class Direction
{
    /**
     * @Enum({"NORTH", "SOUTH", "EAST", "WEST"})
     */
    public $value;
}

注解用法

/** @Direction("NORTH") */
public $direction;                  // Valid value

 /** @Direction("NORTHEAST") */
public $direction;                  // Invalid value, throws an AnnotationException

常量

在注解解析器中可以使用常量和类常量。

以下使用方式是被允许的:

use MyCompany\Annotations\Foo;
use MyCompany\Annotations\Bar;
use MyCompany\Entity\SomeClass;

/**
 * @Foo(PHP_EOL)
 * @Bar(Bar::FOO)
 * @Foo({SomeClass::FOO, SomeClass::BAR})
 * @Bar({SomeClass::FOO_KEY = SomeClass::BAR_VALUE})
 */
class User
{
}

请注意常量和缓存!

缓存读取器在从缓存中加载每个注解时不会重新评估。当常量更改时,必须清理缓存。

使用示例

创建注解类

<?php
/**
 * @Annotation
 * @Target({"CLASS"})
 */
class ServiceDescription
{
    /** @var string */
    private $description;

    /** @var array<ServiceMethod> */
    private $methods;

    public function __construct(array $values)
    {
        $this->description = $values['description'] ?? [];
        $this->methods = $values['methods'] ?? [];
    }
}
<?php
/**
 * @Annotation
 * @Target({"CLASS", "ANNOTATION"})
 */
class ServiceMethod
{
    /** @var string */
    private $name;

    /** @var string */
    private $description;

    public function __construct(array $values)
    {
        $this->name = $values['name'];
        $this->description = $values['description'];
    }
}

在目标类中编写注解

...
/**
 * Class ReportDataService
 * @ServiceDescription(
 *      description = "Service description",
 *      methods = {
 *          @ServiceMethod(
 *              name="delete",
 *              description="delete ReportData method description"
 *          ),
 *          @ServiceMethod(
 *              name="getAll",
 *              description="getAll ReportData method description"
 *          ),
 *          @ServiceMethod(
 *              name="update",
 *              description="update ReportData method description"
 *          ),
 *          @ServiceMethod(
 *              name="count",
 *              description="count ReportData method description"
 *          )
 *     }
 * )
 */
class ReportDataService extends BaseModelService
...
<?php
...
$reader = Yii::$app->annotations->getReader();
...

读取器API

访问类的所有注解

$reader->getClassAnnotations(\ReflectionClass $class);

访问类的一个注解

$reader->getClassAnnotation(\ReflectionClass $class, $annotationName);

访问方法的所有注解

$reader->getMethodAnnotations(\ReflectionMethod $method);

访问方法的一个注解

$reader->getMethodAnnotation(\ReflectionMethod $method, $annotationName);

访问属性的所有注解

$reader->getPropertyAnnotations(\ReflectionProperty $property);

访问属性的一个注解

$reader->getPropertyAnnotation(\ReflectionProperty $property, $annotationName);

获取解析器

直接从docBlock解析注解。它不会被缓存

<?php
...
$reader = Yii::$app->annotations->getParser([
    'annotationName' => AnnotationClass::class
]);
...