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?