Les annotations ont d'abord été introduites en Java. Elles font partie intégrante du langage depuis sa version 5, et sont utilisées de façon assez intensive par certains frameworks, comme par exemple Hibernate. D'autres langages y viennent peu à peu.

Les annotations sont insérées dans les commentaires, en utilisant généralement une syntaxe proche de celle des balises de documentation, c'est à dire de la forme:

/**
 * @cle valeur
 */

Leurs usages sont nombreux:

  • elles peuvent fournir des informations pour réaliser le "mapping" entre une classe PHP et un objet externe, par exemple dans le cadre d'un ORM ou pour optimiser la sérialisation / désérialisation ou la persistence d'objets. Elles évitent ainsi d'utiliser des fichiers de configuration externe. Il est plus simple et plus sûr d'utiliser des annotations dans le code pour ce genre de fonctionnalités, que de devoir pour chaque classe maintenir en parallèle le code et un fichier de configuration;
  • elles sont bien sûr utilisées abondamment lorsqu'on fait de l'inversion de contrôle et de l'injection de dépendances, pour définir précisément les conditions d'appel d'une méthode, les données à y injecter, etc;
  • certains frameworks de tests utilisent des annotations pour "automatiser" une partie des tests. C'est le cas par exemple de PHPUnit

Les annotation restent malheureusement peu utilisées en PHP, peut-être à cause du manque de bibliothèque connue pour les gérer. L'API de réflexion du langage les ignore, et si PEAR contient bien un paquet PHP Annotation, celui-ci il n'est pas téléchargeable (il faut récupérer le source dans le CSV) et n'a pas évolué depuis plusieurs années. Chaque projet désireux d'utiliser des annotations développe donc sa propre méthode, rarement utilisable hors du projet. Et c'est fort dommage, car les annotations sont un mécanisme utile et guère compliqué à mettre en œuvre, un simple parsing à coup d'expressions régulières de commentaires.

J'ai donc été heureux de découvrir addendum, une bibliothèque de gestion des annotations en PHP.

Addendum permet de gérer les annotations sans valeur, ou avec une ou plusieurs valeurs (je reprend des exemples de la documentation du projet :

/**
 * @SimpleAnnotation
 * @SingleValuedAnnotation(true)
 * @SingleValuedAnnotation(-3.141592)
 * @SingleValuedAnnotation('Hello World!')
 * @SingleValuedAnnotationWithArray({1, 2, 3})
 * @MultiValuedAnnotation(role = "admin", level = 2)
 */
class toto {

Addendum propose trois classes, ReflectionAnnotatedClass, ReflectionAnnotatedMethod et ReflectionAnnotatedProperty, qui étendent respectivement les classes natives ReflectionClass, ReflectionMethod, et ReflectionProperty. Elles offrent chacune des méthodes permettant d'accéder aux annotations sur les classes, méthodes et propriétés. Toutes les annotations doivent elles dériver de la classe Annotation. L'exemple précédent suppose donc la création préalable des classes correspondantes, par exemple:

class @MultiValuedAnnotation extends Annotation {
  public role;
  public level;
}

Les annotations crées, on pourra par exemple écrire :

$titi    = new toto();
$reflect = new ReflectionAnnotatedClass($titi)
$annot   = $reflect->getAnnnotation('MultiValuedAnnotation')
$role    = $annot->role;
// ou
$role = new ReflectionAnnotatedClass('toto')->getAnnnotation('MultiValuedAnnotation')->role;

Lors de la définition d'annotations, on peut utiliser l'annotation @Target pour restreindre leur cible. Par exemple, pour définir une annotation utilisable uniquement avec des méthodes, on écrira:

/** @Target("method") */
class Route extends Annotation {}

Addendum semble exister depuis 2006, et est déjà utilisée dans plusieurs projets:

Au final, mon principal regret est que cette bibliothèque n'intègre pas PEAR, ce qui lui confèrerait sans doute la notoriété dont elle manque.