Created
November 17, 2010 03:25
-
-
Save alecgorge/702925 to your computer and use it in GitHub Desktop.
How I think attributes should go down.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class WebService extends Attribute { | |
public $baseURI = ""; | |
public $name = ""; | |
public $desc = ""; | |
public function __construct ($baseURI, $name, $desc) { | |
$this->baseURI = $baseURI; | |
$this->name = $name; | |
$this->desc = $desc; | |
} | |
} | |
class WebMethod extends Attribute { | |
public $uri = ""; | |
public $name = ""; | |
public $desc = ""; | |
public $argDocs = array(); | |
public function __construct ($uri, $name, $desc, $argumentDocs) { | |
$this->uri = $uri; | |
$this->name = $name; | |
$this->desc = $desc; | |
$this->argDocs = $argumentDocs; | |
} | |
} | |
class WebServer { | |
private $subclass = ""; | |
private $serviceURI = ""; | |
private $serviceName = ""; | |
private $serviceDesc = ""; | |
private $urlMapping = array(); | |
public function __construct($subclass) { | |
$this->subclass = $subclass; | |
} | |
public function start () { | |
$r = new ReflectionClass($this->subclass); | |
/** | |
* I think getAnnotations should return an array of annotations matching the name because you should be | |
* able to have multiple annotations with the same name. This also uses function array dereferencing. | |
* | |
* @url http://wiki.php.net/rfc/functionarraydereferencing | |
*/ | |
$classInfo = $r->getAnnotations("WebService")[0]; | |
// I foresee $classInfo containing an instance of the WebService object | |
$this->serviceURI = $classInfo->baseURI; | |
$this->serviceName = $classInfo->name; | |
$this->serviceDesc = $classInfo->desc; | |
// now to get all the public methods (static and otherwise) | |
$methods = $r->getMethods(); | |
foreach($methods as $method) { | |
$methodInfos = $method->getAnnotations("WebMethod"); | |
// $methodInfo is an empty array, not null if no matches are found | |
if(!empty($methodInfos)) { | |
foreach($methodInfos as $info) { | |
if(!empty($this->urlMapping[$info->uri])) { | |
throw new Exception("URI {$this->serviceURI}{$info->uri} is already in use!"); | |
return; | |
} | |
// binds the specified uri to the method | |
$this->urlMapping[$info->uri] = $method; | |
} | |
} | |
} | |
/* everything is bound, now just to parse the url and call the appropriate method | |
$method now equals the string from the URI that is the method and $args is the array of args. | |
For the url being "/api/multiply/4/5", $method = "test" and $args = array(4,5). | |
This is just a simple example, but you could make the attributes so they say what type | |
each argument needs to be, then you can validate the arguments at this point and throw | |
the proper exception/give an invalid argument response. | |
*/ | |
if(array_key_exists($method, $this->urlMapping)) { | |
// This works because you can call the methods of child classes. | |
echo json_encode(call_user_func_array(array($this, $this->urlMapping[$method]->getName()), $args)); | |
exit(); | |
} | |
else { | |
throw new Exception("Method '{$method}' doesn't exist!"); | |
} | |
} | |
} | |
attribute WebService("/api/", "My Web Api", "The description of my Web API"); | |
class MyWebService extends WebServer { | |
public function __construct() { | |
parent::__construct(get_class($this)); | |
} | |
// doQuery is exposed through /api/multiply | |
attribute WebMethod("multiply", "The query method", "The description of the query method.", array( | |
"Some documentation for arg1", | |
"Some docs for arg2" | |
); | |
public function doQuery ($x, $y) { | |
return $x * $y; | |
} | |
} | |
$server = new MyWebService(); | |
$server->start(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment