| 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);
 |