Parę dni wstecz trafiłem na ciekawe rozszerzenie Reflection API do PHP. Umożliwia ono używanie tagów phpdoc w charakterze adnotacji. Rozwiązanie te jest zbliżone do znanego mi z Javy xdocleta. Drobną, aczkolwiek zauważalną, różnicą jest fakt, że xdoclet był odpalany przed kompilacją kodu ponieważ bytecode nie zawierał adnotacji. Oczywiście po wejściu Javy 5 xdoclet podupadł, jako coś co wyparły właśnie adnotacje. Może dla tych, którzy nie mieli okazji spotkania sie z takim rozwiązaniem drobny przykład kodu w Javie: [sourcecode language=“java”]package pl.dywicki.swe.domain;

import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table;

@Entity(name = “user”) @Table(name = “user”, schema = “public”) public class User {

@Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = “user_id”) private long id;

@Column(name=“user_login”) private String login;

@Column(name=“user_password”) private String password;

public long getId() { return id; }

public void setId(long id) { this.id = id; }

public String getLogin() { return login; }

public void setLogin(String login) { this.login = login; }

public String getPassword() { return password; }

public void setPassword(String password) { this.password = password; }

} [/sourcecode]

Co umożliwia takie rozwiązanie? Przede wszystkim dzięki zastosowaniu adnotacji spada ilość dodatkowych plików zawierających konfiguracje i mapowania. Oczywiście nie da się ich dzięki temu rozwiązaniu wykluczyć zupełnie, aczkolwiek da się znacznie ograniczyć ich użycie. Wielką zaletą, o której do tej pory nie wspomniałem, w przypadku Javy, jest to, że adnotacje możemy odczytywać w czasie uruchamiania programu a nie przed jego kompilacją.

Adnotacja od strony technicznej

Jak można zadeklarować własną adnotację? Służy do tego specjalna konstrukcja: [sourcecode language=“java”]public @interface Name { String value() default “anonymous”; }[/sourcecode] Użycie takiej adnotacji: [sourcecode language=“java”]@Name // poprawnie public class Component {}

@Name(“user.session”) // również poprawnie public class User {} [/sourcecode]

Możemy również przekazać kilka wartości gdy zadeklarujemy w adnotacji odpowiednie pole: [sourcecode language=“java”]public @interface Relation { String[] belongsTo(); String offer(); }[/sourcecode] Użycie takiej adnotacji: [sourcecode language=“java”]@Relation(belongTo = {“users”, “groups”}, offer = “privileges”) public class PrivilegesEntityMapping {}[/sourcecode]

Warto tutaj wspomnieć o dwóch magicznych umowach. Po pierwsze atrybut o nazwie value jest domyślnym przypisaniem wartości podanej w nawiasach. Tzn przy wywołaniu @Name(“user.session”) możemy pobrać atrybut poprzez annotationInstance.value(). Po drugie dodanie po nazwie pola default “wartość” pozwala na pominięcie atrybutu przy definicji. Z ograniczeń, jakie mają adnotacje w Javie - wartościami atrybutów mogą być ciągi znaków, typy (klasy) oraz typy wyliczeniowe (enumy).

Jak użyć adnotacji? Korzystając z reflection api. [sourcecode language=“java”]Name instance = getClass().getAnnotation(Name.class); // Name.class to typ naszej adnotacji. System.out.println(instance.value());[/sourcecode]

Adnotacje a PHP

Jak wcześniej wspominałem, adnotacje nie są elementem PHP, chociaż ludzie pokusili się już o zbudowanie mechanizmu podobnego do tego, który jest w Javie. Jednym z takich projektów jest Addendum. Warto zaznaczyć, że nie jest to nazwa wyssana z palca a słowo “addendum” ma swoje znaczenie również w języku polskim i ogólnie rzecz biorąc znaczy dodatek do jakiegoś tekstu (więcej informacji na wikisłowniku).

Jak wygląda użycie adnotacji w PHP? Jednym z przykładów może być Torpedeo. Projekt tego samego autora co Addendum, będący implementacją lekkiego ORMa. Przykładowa deklaracja obsługiwana przez Torpedeo: [sourcecode language=“php”]<?php /\\ \* @Table(’nodes’) */ class Node { /\\ @Integer */ public $id;

/\\ @String */ public $title;

/\\ \* @Integer \* @Nullable \* @Column(‘parent_id’); */ public $parentId;

/\\ @Boolean */ public $visible; } ?>[/sourcecode]

Addendum wymaga by klasy adnotacji rozszerzały klasę Annotation: [sourcecode language=“php”][/sourcecode] Dodatkowo biblioteka dostarcza rozszerzeń reflection API z PHP5 umożliwiające odczytywanie adnotacji. Dokładny tutorial jak używać tego narzędzia można znaleźć na oficjalnej stronie projektu.

Adnotacje w PHP?

Pytanie czy adnotacje w PHP przyjmą się tak samo dobrze jak w Javie? Zdaje się, że by o tym mówić jest zbyt wcześnie, ponieważ projektów, które korzystają z tego mechanizmu jest na chwilę obecną bardzo mało. Sądząc jednak po tym jak szybko rozwinął się xdoclet można twierdzić, że to tylko kwestia czasu. Chociaż.. może w Javie po prostu jest więcej plików konfiguracyjnych?