444 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			444 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
Custom Annotation Classes
 | 
						|
=========================
 | 
						|
 | 
						|
If you want to define your own annotations, you just have to group them
 | 
						|
in a namespace.
 | 
						|
Annotation classes have to contain a class-level docblock with the text
 | 
						|
``@Annotation``:
 | 
						|
 | 
						|
.. code-block:: php
 | 
						|
 | 
						|
    namespace MyCompany\Annotations;
 | 
						|
 | 
						|
    /** @Annotation */
 | 
						|
    class Bar
 | 
						|
    {
 | 
						|
        // some code
 | 
						|
    }
 | 
						|
 | 
						|
Inject annotation values
 | 
						|
------------------------
 | 
						|
 | 
						|
The annotation parser checks if the annotation constructor has arguments,
 | 
						|
if so then it will pass the value array, otherwise it will try to inject
 | 
						|
values into public properties directly:
 | 
						|
 | 
						|
 | 
						|
.. code-block:: php
 | 
						|
 | 
						|
    namespace MyCompany\Annotations;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @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;
 | 
						|
    }
 | 
						|
 | 
						|
Optional: Constructors with Named Parameters
 | 
						|
--------------------------------------------
 | 
						|
 | 
						|
Starting with Annotations v1.11 a new annotation instantiation strategy
 | 
						|
is available that aims at compatibility of Annotation classes with the PHP 8
 | 
						|
attribute feature. You need to declare a constructor with regular parameter
 | 
						|
names that match the named arguments in the annotation syntax.
 | 
						|
 | 
						|
To enable this feature, you can tag your annotation class with
 | 
						|
``@NamedArgumentConstructor`` (available from v1.12) or implement the
 | 
						|
``Doctrine\Common\Annotations\NamedArgumentConstructorAnnotation`` interface
 | 
						|
(available from v1.11 and deprecated as of v1.12).
 | 
						|
When using the ``@NamedArgumentConstructor`` tag, the first argument of the
 | 
						|
constructor is considered as the default one.
 | 
						|
 | 
						|
 | 
						|
Usage with the ``@NamedArgumentConstructor`` tag
 | 
						|
 | 
						|
.. code-block:: php
 | 
						|
 | 
						|
    namespace MyCompany\Annotations;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @Annotation
 | 
						|
     * @NamedArgumentConstructor
 | 
						|
     */
 | 
						|
    class Bar implements NamedArgumentConstructorAnnotation
 | 
						|
    {
 | 
						|
        private $foo;
 | 
						|
 | 
						|
        public function __construct(string $foo)
 | 
						|
        {
 | 
						|
            $this->foo = $foo;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /** Usable with @Bar(foo="baz") */
 | 
						|
    /** Usable with @Bar("baz") */
 | 
						|
 | 
						|
In combination with PHP 8's constructor property promotion feature
 | 
						|
you can simplify this to:
 | 
						|
 | 
						|
.. code-block:: php
 | 
						|
 | 
						|
    namespace MyCompany\Annotations;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @Annotation
 | 
						|
     * @NamedArgumentConstructor
 | 
						|
     */
 | 
						|
    class Bar implements NamedArgumentConstructorAnnotation
 | 
						|
    {
 | 
						|
        public function __construct(private string $foo) {}
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
Usage with the
 | 
						|
``Doctrine\Common\Annotations\NamedArgumentConstructorAnnotation``
 | 
						|
interface (v1.11, deprecated as of v1.12):
 | 
						|
.. code-block:: php
 | 
						|
 | 
						|
    namespace MyCompany\Annotations;
 | 
						|
 | 
						|
    use Doctrine\Common\Annotations\NamedArgumentConstructorAnnotation;
 | 
						|
 | 
						|
    /** @Annotation */
 | 
						|
    class Bar implements NamedArgumentConstructorAnnotation
 | 
						|
    {
 | 
						|
        private $foo;
 | 
						|
 | 
						|
        public function __construct(private string $foo) {}
 | 
						|
    }
 | 
						|
 | 
						|
    /** Usable with @Bar(foo="baz") */
 | 
						|
 | 
						|
Annotation Target
 | 
						|
-----------------
 | 
						|
 | 
						|
``@Target`` indicates the kinds of class elements to which an annotation
 | 
						|
type is applicable. Then you could define one or more targets:
 | 
						|
 | 
						|
-  ``CLASS`` Allowed in class docblocks
 | 
						|
-  ``PROPERTY`` Allowed in property docblocks
 | 
						|
-  ``METHOD`` Allowed in the method docblocks
 | 
						|
-  ``FUNCTION`` Allowed in function dockblocks
 | 
						|
-  ``ALL`` Allowed in class, property, method and function docblocks
 | 
						|
-  ``ANNOTATION`` Allowed inside other annotations
 | 
						|
 | 
						|
If the annotations is not allowed in the current context, an
 | 
						|
``AnnotationException`` is thrown.
 | 
						|
 | 
						|
.. code-block:: php
 | 
						|
 | 
						|
    namespace MyCompany\Annotations;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @Annotation
 | 
						|
     * @Target({"METHOD","PROPERTY"})
 | 
						|
     */
 | 
						|
    class Bar
 | 
						|
    {
 | 
						|
        // some code
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @Annotation
 | 
						|
     * @Target("CLASS")
 | 
						|
     */
 | 
						|
    class Foo
 | 
						|
    {
 | 
						|
        // some code
 | 
						|
    }
 | 
						|
 | 
						|
Attribute types
 | 
						|
---------------
 | 
						|
 | 
						|
The annotation parser checks the given parameters using the phpdoc
 | 
						|
annotation ``@var``, The data type could be validated using the ``@var``
 | 
						|
annotation on the annotation properties or using the ``@Attributes`` and
 | 
						|
``@Attribute`` annotations.
 | 
						|
 | 
						|
If the data type does not match you get an ``AnnotationException``
 | 
						|
 | 
						|
.. code-block:: php
 | 
						|
 | 
						|
    namespace MyCompany\Annotations;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @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
 | 
						|
    }
 | 
						|
 | 
						|
Annotation Required
 | 
						|
-------------------
 | 
						|
 | 
						|
``@Required`` indicates that the field must be specified when the
 | 
						|
annotation is used. If it is not used you get an ``AnnotationException``
 | 
						|
stating that this value can not be null.
 | 
						|
 | 
						|
Declaring a required field:
 | 
						|
 | 
						|
.. code-block:: php
 | 
						|
 | 
						|
    /**
 | 
						|
     * @Annotation
 | 
						|
     * @Target("ALL")
 | 
						|
     */
 | 
						|
    class Foo
 | 
						|
    {
 | 
						|
        /** @Required */
 | 
						|
        public $requiredField;
 | 
						|
    }
 | 
						|
 | 
						|
Usage:
 | 
						|
 | 
						|
.. code-block:: php
 | 
						|
 | 
						|
    /** @Foo(requiredField="value") */
 | 
						|
    public $direction;                  // Valid
 | 
						|
 | 
						|
     /** @Foo */
 | 
						|
    public $direction;                  // Required field missing, throws an AnnotationException
 | 
						|
 | 
						|
 | 
						|
Enumerated values
 | 
						|
-----------------
 | 
						|
 | 
						|
- An annotation property marked with ``@Enum`` is a field that accepts a
 | 
						|
  fixed set of scalar values.
 | 
						|
- You should use ``@Enum`` fields any time you need to represent fixed
 | 
						|
  values.
 | 
						|
- The annotation parser checks the given value and throws an
 | 
						|
  ``AnnotationException`` if the value does not match.
 | 
						|
 | 
						|
 | 
						|
Declaring an enumerated property:
 | 
						|
 | 
						|
.. code-block:: php
 | 
						|
 | 
						|
    /**
 | 
						|
     * @Annotation
 | 
						|
     * @Target("ALL")
 | 
						|
     */
 | 
						|
    class Direction
 | 
						|
    {
 | 
						|
        /**
 | 
						|
         * @Enum({"NORTH", "SOUTH", "EAST", "WEST"})
 | 
						|
         */
 | 
						|
        public $value;
 | 
						|
    }
 | 
						|
 | 
						|
Annotation usage:
 | 
						|
 | 
						|
.. code-block:: php
 | 
						|
 | 
						|
    /** @Direction("NORTH") */
 | 
						|
    public $direction;                  // Valid value
 | 
						|
 | 
						|
     /** @Direction("NORTHEAST") */
 | 
						|
    public $direction;                  // Invalid value, throws an AnnotationException
 | 
						|
 | 
						|
 | 
						|
Constants
 | 
						|
---------
 | 
						|
 | 
						|
The use of constants and class constants is available on the annotations
 | 
						|
parser.
 | 
						|
 | 
						|
The following usages are allowed:
 | 
						|
 | 
						|
.. code-block:: php
 | 
						|
 | 
						|
    namespace MyCompany\Entity;
 | 
						|
 | 
						|
    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
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
Be careful with constants and the cache !
 | 
						|
 | 
						|
.. note::
 | 
						|
 | 
						|
    The cached reader will not re-evaluate each time an annotation is
 | 
						|
    loaded from cache. When a constant is changed the cache must be
 | 
						|
    cleaned.
 | 
						|
 | 
						|
 | 
						|
Usage
 | 
						|
-----
 | 
						|
 | 
						|
Using the library API is simple. Using the annotations described in the
 | 
						|
previous section, you can now annotate other classes with your
 | 
						|
annotations:
 | 
						|
 | 
						|
.. code-block:: php
 | 
						|
 | 
						|
    namespace MyCompany\Entity;
 | 
						|
 | 
						|
    use MyCompany\Annotations\Foo;
 | 
						|
    use MyCompany\Annotations\Bar;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @Foo(bar="foo")
 | 
						|
     * @Bar(foo="bar")
 | 
						|
     */
 | 
						|
    class User
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
Now we can write a script to get the annotations above:
 | 
						|
 | 
						|
.. code-block:: php
 | 
						|
 | 
						|
    $reflClass = new ReflectionClass('MyCompany\Entity\User');
 | 
						|
    $classAnnotations = $reader->getClassAnnotations($reflClass);
 | 
						|
 | 
						|
    foreach ($classAnnotations AS $annot) {
 | 
						|
        if ($annot instanceof \MyCompany\Annotations\Foo) {
 | 
						|
            echo $annot->bar; // prints "foo";
 | 
						|
        } else if ($annot instanceof \MyCompany\Annotations\Bar) {
 | 
						|
            echo $annot->foo; // prints "bar";
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
You have a complete API for retrieving annotation class instances from a
 | 
						|
class, property or method docblock:
 | 
						|
 | 
						|
 | 
						|
Reader API
 | 
						|
~~~~~~~~~~
 | 
						|
 | 
						|
Access all annotations of a class
 | 
						|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 | 
						|
 | 
						|
.. code-block:: php
 | 
						|
 | 
						|
    public function getClassAnnotations(\ReflectionClass $class);
 | 
						|
 | 
						|
Access one annotation of a class
 | 
						|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 | 
						|
 | 
						|
.. code-block:: php
 | 
						|
 | 
						|
    public function getClassAnnotation(\ReflectionClass $class, $annotationName);
 | 
						|
 | 
						|
Access all annotations of a method
 | 
						|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 | 
						|
 | 
						|
.. code-block:: php
 | 
						|
 | 
						|
    public function getMethodAnnotations(\ReflectionMethod $method);
 | 
						|
 | 
						|
Access one annotation of a method
 | 
						|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 | 
						|
 | 
						|
.. code-block:: php
 | 
						|
 | 
						|
    public function getMethodAnnotation(\ReflectionMethod $method, $annotationName);
 | 
						|
 | 
						|
Access all annotations of a property
 | 
						|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 | 
						|
 | 
						|
.. code-block:: php
 | 
						|
 | 
						|
    public function getPropertyAnnotations(\ReflectionProperty $property);
 | 
						|
 | 
						|
Access one annotation of a property
 | 
						|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 | 
						|
 | 
						|
.. code-block:: php
 | 
						|
 | 
						|
    public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName);
 | 
						|
 | 
						|
Access all annotations of a function
 | 
						|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 | 
						|
 | 
						|
.. code-block:: php
 | 
						|
 | 
						|
    public function getFunctionAnnotations(\ReflectionFunction $property);
 | 
						|
 | 
						|
Access one annotation of a function
 | 
						|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 | 
						|
 | 
						|
.. code-block:: php
 | 
						|
 | 
						|
    public function getFunctionAnnotation(\ReflectionFunction $property, $annotationName);
 |