PHP でアノテーション
PHP フレームワーク構想 - devworksのエントリで
Validation は PHP コメントアノテーションを読み込んで自動実行
PHP フレームワーク構想 - devworks
と、書いたのでちょっとアノテーションについて調べてみました。まずは Class/Method/Field のDoccomment を取得してみます。
<?php /* * To change this template, choose Tools | Templates * and open the template in the editor. */ /** * Description of index * @author devworks * @clazz_ano1 * @clazz_ano2(hoge) * @clazza_ano3(foo, bar) */ class AnnotationTest { /** * @field_ano1 * @field_ano2(hoge) * @field_ano3(foo, bar) * @var <type> */ private $ano; /** * @method_ano1 * @method_ano2(hoge) * @method_ano3(foo, bar) */ public function anoTest() { } } $clazz = new ReflectionClass("AnnotationTest"); echo $clazz -> getDocComment(); echo "<br />"; $method = $clazz -> getMethod("anoTest"); echo $method -> getDocComment(); echo "<br />"; $field = $clazz -> getProperty("ano"); echo $field -> getDocComment(); ?>
結果はこんな感じ。
/** * Description of index * @author devworks * @clazz_ano1 * @clazz_ano2(hoge) * @clazza_ano3(foo, bar) */ /** * @method_ano1 * @method_ano2(hoge) * @method_ano3(foo, bar) */ /** * @field_ano1 * @field_ano2(hoge) * @field_ano3(foo, bar) * @var */
Doccomment が全て取得できてますね。では「@」の部分だけ取得してみましょう。
<?php // AnnotationTest は省略 class AnnotationReader { /** * ReflectionClass * @var ReflectionClass */ public $clazz; public function __construct($name) { $this->clazz = new ReflectionClass($name); } public function getClassAnnotation() { $comment = $this->getDocComment($this->clazz->getDocComment()); $this->getAnnotation($comment); } public function getMethodAnnotation($name) { $method = $clazz->getMethod($name); $comment = $this->getDocComment($method->getDocComment()); $this->getAnnotation($comment); } public function getFieldAnnotation($name) { $field = $clazz->getProperty($name); $comment = $this->getDocComment($field->getDocComment()); $this->getAnnotation($comment); } private function getDocComment($docComment) { return preg_split("/[\n\r]/", $docComment, -1, PREG_SPLIT_NO_EMPTY); } private function getAnnotation($comments) { foreach ($comments as $line) { $line = $this->_removeCommentSlashAster($line); if (preg_match("/^@\w+$/",$line) or preg_match("/^@\w+\s*\(/",$line)) { echo $line."<br />"; } } } private function _removeCommentSlashAster($line) { $line = trim($line); $line = preg_replace("/^\/\*\*/","",$line); $line = preg_replace("/\*\/$/","",$line); $line = preg_replace("/^\*/","",$line); return trim($line); } }
で、以下みたいに実行すると
$ano = new AnnotationReader("AnnotationTest");
$ano->getClassAnnotation();
@clazz_ano1 @clazz_ano2(hoge) @clazza_ano3(foo, bar)
とれましたね。S2PHP5 のソースをぱくったのでここまでは OK。あとは取得できたアノテーションと同名のクラスをインスタンス化しなければなりません。S2PHP5 の場合はコンテナから取得しているのですが、僕のフレームワークでは DI の予定はないので __autoload を実装して annotation ディレクトリにいるアノテーションと同名のファイル名を探して includeしようと思います。
というわけで残りは次回。