custom.rst 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. Custom Annotation Classes
  2. =========================
  3. If you want to define your own annotations, you just have to group them
  4. in a namespace and register this namespace in the ``AnnotationRegistry``.
  5. Annotation classes have to contain a class-level docblock with the text
  6. ``@Annotation``:
  7. .. code-block:: php
  8. namespace MyCompany\Annotations;
  9. /** @Annotation */
  10. class Bar
  11. {
  12. // some code
  13. }
  14. Inject annotation values
  15. ------------------------
  16. The annotation parser checks if the annotation constructor has arguments,
  17. if so then it will pass the value array, otherwise it will try to inject
  18. values into public properties directly:
  19. .. code-block:: php
  20. namespace MyCompany\Annotations;
  21. /**
  22. * @Annotation
  23. *
  24. * Some Annotation using a constructor
  25. */
  26. class Bar
  27. {
  28. private $foo;
  29. public function __construct(array $values)
  30. {
  31. $this->foo = $values['foo'];
  32. }
  33. }
  34. /**
  35. * @Annotation
  36. *
  37. * Some Annotation without a constructor
  38. */
  39. class Foo
  40. {
  41. public $bar;
  42. }
  43. Optional: Constructors with Named Parameters
  44. --------------------------------------------
  45. Starting with Annotations v1.11 a new annotation instantiation strategy
  46. is available that aims at compatibility of Annotation classes with the PHP 8
  47. attribute feature. You need to declare a constructor with regular parameter
  48. names that match the named arguments in the annotation syntax.
  49. To enable this feature, you can tag your annotation class with
  50. ``@NamedArgumentConstructor`` (available from v1.12) or implement the
  51. ``Doctrine\Common\Annotations\NamedArgumentConstructorAnnotation`` interface
  52. (available from v1.11 and deprecated as of v1.12).
  53. When using the ``@NamedArgumentConstructor`` tag, the first argument of the
  54. constructor is considered as the default one.
  55. Usage with the ``@NamedArgumentContrustor`` tag
  56. .. code-block:: php
  57. namespace MyCompany\Annotations;
  58. /**
  59. * @Annotation
  60. * @NamedArgumentConstructor
  61. */
  62. class Bar implements NamedArgumentConstructorAnnotation
  63. {
  64. private $foo;
  65. public function __construct(string $foo)
  66. {
  67. $this->foo = $foo;
  68. }
  69. }
  70. /** Usable with @Bar(foo="baz") */
  71. /** Usable with @Bar("baz") */
  72. In combination with PHP 8's constructor property promotion feature
  73. you can simplify this to:
  74. .. code-block:: php
  75. namespace MyCompany\Annotations;
  76. /**
  77. * @Annotation
  78. * @NamedArgumentConstructor
  79. */
  80. class Bar implements NamedArgumentConstructorAnnotation
  81. {
  82. public function __construct(private string $foo) {}
  83. }
  84. Usage with the
  85. ``Doctrine\Common\Annotations\NamedArgumentConstructorAnnotation``
  86. interface (v1.11, deprecated as of v1.12):
  87. .. code-block:: php
  88. namespace MyCompany\Annotations;
  89. use Doctrine\Common\Annotations\NamedArgumentConstructorAnnotation;
  90. /** @Annotation */
  91. class Bar implements NamedArgumentConstructorAnnotation
  92. {
  93. private $foo;
  94. public function __construct(private string $foo) {}
  95. }
  96. /** Usable with @Bar(foo="baz") */
  97. Annotation Target
  98. -----------------
  99. ``@Target`` indicates the kinds of class elements to which an annotation
  100. type is applicable. Then you could define one or more targets:
  101. - ``CLASS`` Allowed in class docblocks
  102. - ``PROPERTY`` Allowed in property docblocks
  103. - ``METHOD`` Allowed in the method docblocks
  104. - ``FUNCTION`` Allowed in function dockblocks
  105. - ``ALL`` Allowed in class, property, method and function docblocks
  106. - ``ANNOTATION`` Allowed inside other annotations
  107. If the annotations is not allowed in the current context, an
  108. ``AnnotationException`` is thrown.
  109. .. code-block:: php
  110. namespace MyCompany\Annotations;
  111. /**
  112. * @Annotation
  113. * @Target({"METHOD","PROPERTY"})
  114. */
  115. class Bar
  116. {
  117. // some code
  118. }
  119. /**
  120. * @Annotation
  121. * @Target("CLASS")
  122. */
  123. class Foo
  124. {
  125. // some code
  126. }
  127. Attribute types
  128. ---------------
  129. The annotation parser checks the given parameters using the phpdoc
  130. annotation ``@var``, The data type could be validated using the ``@var``
  131. annotation on the annotation properties or using the ``@Attributes`` and
  132. ``@Attribute`` annotations.
  133. If the data type does not match you get an ``AnnotationException``
  134. .. code-block:: php
  135. namespace MyCompany\Annotations;
  136. /**
  137. * @Annotation
  138. * @Target({"METHOD","PROPERTY"})
  139. */
  140. class Bar
  141. {
  142. /** @var mixed */
  143. public $mixed;
  144. /** @var boolean */
  145. public $boolean;
  146. /** @var bool */
  147. public $bool;
  148. /** @var float */
  149. public $float;
  150. /** @var string */
  151. public $string;
  152. /** @var integer */
  153. public $integer;
  154. /** @var array */
  155. public $array;
  156. /** @var SomeAnnotationClass */
  157. public $annotation;
  158. /** @var array<integer> */
  159. public $arrayOfIntegers;
  160. /** @var array<SomeAnnotationClass> */
  161. public $arrayOfAnnotations;
  162. }
  163. /**
  164. * @Annotation
  165. * @Target({"METHOD","PROPERTY"})
  166. * @Attributes({
  167. * @Attribute("stringProperty", type = "string"),
  168. * @Attribute("annotProperty", type = "SomeAnnotationClass"),
  169. * })
  170. */
  171. class Foo
  172. {
  173. public function __construct(array $values)
  174. {
  175. $this->stringProperty = $values['stringProperty'];
  176. $this->annotProperty = $values['annotProperty'];
  177. }
  178. // some code
  179. }
  180. Annotation Required
  181. -------------------
  182. ``@Required`` indicates that the field must be specified when the
  183. annotation is used. If it is not used you get an ``AnnotationException``
  184. stating that this value can not be null.
  185. Declaring a required field:
  186. .. code-block:: php
  187. /**
  188. * @Annotation
  189. * @Target("ALL")
  190. */
  191. class Foo
  192. {
  193. /** @Required */
  194. public $requiredField;
  195. }
  196. Usage:
  197. .. code-block:: php
  198. /** @Foo(requiredField="value") */
  199. public $direction; // Valid
  200. /** @Foo */
  201. public $direction; // Required field missing, throws an AnnotationException
  202. Enumerated values
  203. -----------------
  204. - An annotation property marked with ``@Enum`` is a field that accepts a
  205. fixed set of scalar values.
  206. - You should use ``@Enum`` fields any time you need to represent fixed
  207. values.
  208. - The annotation parser checks the given value and throws an
  209. ``AnnotationException`` if the value does not match.
  210. Declaring an enumerated property:
  211. .. code-block:: php
  212. /**
  213. * @Annotation
  214. * @Target("ALL")
  215. */
  216. class Direction
  217. {
  218. /**
  219. * @Enum({"NORTH", "SOUTH", "EAST", "WEST"})
  220. */
  221. public $value;
  222. }
  223. Annotation usage:
  224. .. code-block:: php
  225. /** @Direction("NORTH") */
  226. public $direction; // Valid value
  227. /** @Direction("NORTHEAST") */
  228. public $direction; // Invalid value, throws an AnnotationException
  229. Constants
  230. ---------
  231. The use of constants and class constants is available on the annotations
  232. parser.
  233. The following usages are allowed:
  234. .. code-block:: php
  235. namespace MyCompany\Entity;
  236. use MyCompany\Annotations\Foo;
  237. use MyCompany\Annotations\Bar;
  238. use MyCompany\Entity\SomeClass;
  239. /**
  240. * @Foo(PHP_EOL)
  241. * @Bar(Bar::FOO)
  242. * @Foo({SomeClass::FOO, SomeClass::BAR})
  243. * @Bar({SomeClass::FOO_KEY = SomeClass::BAR_VALUE})
  244. */
  245. class User
  246. {
  247. }
  248. Be careful with constants and the cache !
  249. .. note::
  250. The cached reader will not re-evaluate each time an annotation is
  251. loaded from cache. When a constant is changed the cache must be
  252. cleaned.
  253. Usage
  254. -----
  255. Using the library API is simple. Using the annotations described in the
  256. previous section, you can now annotate other classes with your
  257. annotations:
  258. .. code-block:: php
  259. namespace MyCompany\Entity;
  260. use MyCompany\Annotations\Foo;
  261. use MyCompany\Annotations\Bar;
  262. /**
  263. * @Foo(bar="foo")
  264. * @Bar(foo="bar")
  265. */
  266. class User
  267. {
  268. }
  269. Now we can write a script to get the annotations above:
  270. .. code-block:: php
  271. $reflClass = new ReflectionClass('MyCompany\Entity\User');
  272. $classAnnotations = $reader->getClassAnnotations($reflClass);
  273. foreach ($classAnnotations AS $annot) {
  274. if ($annot instanceof \MyCompany\Annotations\Foo) {
  275. echo $annot->bar; // prints "foo";
  276. } else if ($annot instanceof \MyCompany\Annotations\Bar) {
  277. echo $annot->foo; // prints "bar";
  278. }
  279. }
  280. You have a complete API for retrieving annotation class instances from a
  281. class, property or method docblock:
  282. Reader API
  283. ~~~~~~~~~~
  284. Access all annotations of a class
  285. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  286. .. code-block:: php
  287. public function getClassAnnotations(\ReflectionClass $class);
  288. Access one annotation of a class
  289. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  290. .. code-block:: php
  291. public function getClassAnnotation(\ReflectionClass $class, $annotationName);
  292. Access all annotations of a method
  293. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  294. .. code-block:: php
  295. public function getMethodAnnotations(\ReflectionMethod $method);
  296. Access one annotation of a method
  297. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  298. .. code-block:: php
  299. public function getMethodAnnotation(\ReflectionMethod $method, $annotationName);
  300. Access all annotations of a property
  301. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  302. .. code-block:: php
  303. public function getPropertyAnnotations(\ReflectionProperty $property);
  304. Access one annotation of a property
  305. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  306. .. code-block:: php
  307. public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName);
  308. Access all annotations of a function
  309. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  310. .. code-block:: php
  311. public function getFunctionAnnotations(\ReflectionFunction $property);
  312. Access one annotation of a function
  313. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  314. .. code-block:: php
  315. public function getFunctionAnnotation(\ReflectionFunction $property, $annotationName);