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:
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;
}
}
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:
public @interface Name {
String value() default "anonymous";
}
Użycie takiej adnotacji:
@Name // poprawnie
public class Component {}
@Name("user.session") // również poprawnie
public class User {}
Możemy również przekazać kilka wartości gdy zadeklarujemy w adnotacji odpowiednie pole:
public @interface Relation {
String[] belongsTo();
String offer();
}
Użycie takiej adnotacji:
@Relation(belongTo = {"users", "groups"}, offer = "privileges")
public class PrivilegesEntityMapping {}
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.
Name instance = getClass().getAnnotation(Name.class); // Name.class to typ naszej adnotacji.
System.out.println(instance.value());
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:
<?php
/**
* @Table('nodes')
*/
class Node {
/** @Integer */
public $id;
/** @String */
public $title;
/**
* @Integer
* @Nullable
* @Column('parent_id');
*/
public $parentId;
/** @Boolean */
public $visible;
}
?>
Addendum wymaga by klasy adnotacji rozszerzały klasę Annotation:
<?php
class Nullable extends Annotation {}
class Transient extends Annotation {}
?>
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?