PHP でアノテーション 2
/* * @Required * **/ public $var;
と書いておけば、「annotation」ディレクトリの「Required.php」を include_once して new Required() します。
構想としては、上記のように書いておけば Action 実行前に必須チェックを行う。SAStruts みたいな感じですね。次回はアノテーションを取得して Validation を行うところをやろうと思います。
…先にフロントコントローラから作ればよかったな…。
以下ソース。S2PHP5 のソースを参考に作ってます。感謝感謝。
<?php include_once 'AnnotationFactory.php'; class AnnotationReader { /** * ReflectionClass * @var ReflectionClass */ private $clazz; public function __construct($name) { $this->clazz = new ReflectionClass($name); } public function getClassAnnotation() { $comment = $this->getDocComment($this->clazz->getDocComment()); return $this->getAnnotation($comment); } public function getMethodAnnotation($name) { $method = $clazz->getMethod($name); $comment = $this->getDocComment($method->getDocComment()); return $this->getAnnotation($comment); } public function getFieldAnnotation($name) { $field = $clazz->getProperty($name); $comment = $this->getDocComment($field->getDocComment()); return $this->getAnnotation($comment); } private function getDocComment($docComment) { return preg_split("/[\n\r]/", $docComment, -1, PREG_SPLIT_NO_EMPTY); } private function getAnnotation($comments) { $annoObjects = array(); foreach ($comments as $line) { $line = $this->_removeCommentSlashAster($line); if (preg_match("/^@\w+$/",$line) or preg_match("/^@\w+\s*\(/",$line)) { if (preg_match("/^@(\w+)$/",$line,$matches)) { $annoObj = AnnotationFactory::create($matches[1]); $annoObjects[get_class($annoObj)] = $annoObj; } if (preg_match("/^@(\w+)\s*\((.*)\)/",$line,$matches)) { $annotationType = $matches[1]; $items = preg_split("/,/", $matches[2]); $args = array(); $argType = array(); foreach ($items as $item) { if (preg_match("/^(.+?)=(.+)/s",$item,$matches)) { $key = $this->_removeQuote($matches[1]); $val = $this->_removeQuote($matches[2]); if ($key == "") { // Error } $args[$key] = $val; $argType = AnnotationFactory::ARGS_TYPE_HASH; } else { $item = $this->_removeQuote($item); $args[] = $item; echo count($args); echo '<br />'; $argType = AnnotationFactory::ARGS_TYPE_ARRAY; } } $annoObj = AnnotationFactory::create($annotationType, $args, $argType); $annoObjects[get_class($annoObj)] = $annoObj; } } } return $annoObjects; } private function _removeQuote($str) { $str = trim($str); $str = preg_replace("/^[\"']/",'',$str); $str = preg_replace("/[\"']$/",'',$str); return trim($str); } private function _removeCommentSlashAster($line) { $line = trim($line); $line = preg_replace("/^\/\*\*/","",$line); $line = preg_replace("/\*\/$/","",$line); $line = preg_replace("/^\*/","",$line); return trim($line); } } class AnnotationFactory { const ARGS_TYPE_ARRAY = 1; const ARGS_TYPE_HASH = 2; private function __construct() { } public static function create($name, $args = array(), $argType = array()) { $annoObj = new $name(); if (count($args) == 0) { return $annoObj; } if ($argType == self::ARGS_TYPE_ARRAY) { if (count($args) == 1) { $annoObj->value = $args[0]; } else { $annoObj->value = $args; } return $annoObj; } foreach ($args as $arg=>$val) { $annoObj->$arg = $val; } return $annoObj; } } function __autoload($class) { $dir = dirname(__FILE__); $file = $dir . DIRECTORY_SEPARATOR . 'annotation' . DIRECTORY_SEPARATOR . $class . '.php'; if (is_file($file) && is_readable($file)) { include_once $file; if (class_exists($class, false)) { return true; } } return false; } ?>