Easy Web Services   using PHP reflection API phplondon, Dec 4 th  2008
Reflection ?
http://www.flickr.com/photos/bcnbits/368112752/
Reflection <ul><li>In computer science, reflection is the process by which a computer program can observe and modify its o...
Reflection in PHP5 <ul><li>reverse-engineer </li></ul><ul><li>classes,  </li></ul><ul><li>interfaces,  </li></ul><ul><li>e...
Eg. Reflection Method class  ReflectionMethod  extends  […] {   public  bool isFinal ()     public  bool isAbstract ()    ...
Eg. Reflection Method class  Randomizer {          /**       * Returns randomly 0 or 1       * @return  int      */       ...
Reflection is useful for  <ul><li>Why reverse engineer comments in code?  Easy to generate documentation. </li></ul><ul><l...
Reflection is useful for  <ul><li>Annotations, eg. in PHP Unit </li></ul>In this example the test will fail because it doe...
Easy Web Services   Simple use case
Watch out, you will see code   in slides!!!
class  Users { /** *  @return  array the list of all the users */ static public function  getUsers( $limit  = 10) { // eac...
// simple call to the REST API via http $users  = file_get_contents(  &quot;http://service/API/&quot; . &quot;?method=User...
// ResponseBuilder object can convert the data in XML, JSON, CSV // by converting your API returned value (from array, int...
The concept Request comes in, forwarded to Proxy that does the Reflection magic: calls the method on the right class, with...
class  Request  { protected  $request ; function  __construct( $requestString  = null) { if (is_null( $requestString )) { ...
class  Proxy { function  call( $className ,  $methodName ,  $request ) {   $this->setContext( $className ,  $methodName , ...
Conclusion <ul><li>Similar pattern as FrontController / Dispatcher </li></ul><ul><li>One entry point to your Models. You c...
... and use the Proxy class to generate your API documentation (from the code, and by reverse engineering your method comm...
Questions ?
References <ul><li>This pattern is used in the open source Piwik project http://piwik.org </li></ul><ul><li>View the code ...
Upcoming SlideShare
Loading in...5
×

Easy rest service using PHP reflection api

67,706

Published on

Quick presentation of a design pattern: How to automatically expose your classes and methods in a REST service?
+ Presentation of PHP Reflection API.

Published in: Technology
2 Comments
16 Likes
Statistics
Notes
No Downloads
Views
Total Views
67,706
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
325
Comments
2
Likes
16
Embeds 0
No embeds

No notes for slide

Easy rest service using PHP reflection api

  1. 1. Easy Web Services using PHP reflection API phplondon, Dec 4 th 2008
  2. 2. Reflection ?
  3. 3. http://www.flickr.com/photos/bcnbits/368112752/
  4. 4. Reflection <ul><li>In computer science, reflection is the process by which a computer program can observe and modify its own structure and behaviour. </li></ul>
  5. 5. Reflection in PHP5 <ul><li>reverse-engineer </li></ul><ul><li>classes, </li></ul><ul><li>interfaces, </li></ul><ul><li>exceptions </li></ul><ul><li>functions </li></ul><ul><li>Methods </li></ul><ul><li>Parameters </li></ul><ul><li>properties </li></ul><ul><li>extensions </li></ul><ul><li>retrieve doc comments for </li></ul><ul><li>functions, </li></ul><ul><li>classes and </li></ul><ul><li>methods. </li></ul>
  6. 6. Eg. Reflection Method class  ReflectionMethod  extends  […] { public  bool isFinal ()     public  bool isAbstract ()     public  bool isPublic ()     public  bool isPrivate ()     public  bool isProtected ()     public  bool isStatic ()     public  bool isConstructor ()     public  bool isDestructor () […..]     public  string getFileName ()     public  int getStartLine ()     public  int getEndLine ()     public  string getDocComment ()     public array  getStaticVariables ()
  7. 7. Eg. Reflection Method class  Randomizer {          /**       * Returns randomly 0 or 1       * @return  int      */      final public static function  get ()     {         return rand( 0, 1);     } } // Create an instance of the ReflectionMethod class $method  = new  ReflectionMethod ( ‘ Randomizer ' ,  get' ); echo $method -> isConstructor () ?  'the constructor'  :  'a regular method‘ ; printf ( &quot;---> Documentation:  %s &quot; ,  var_export ( $method -> getDocComment (),  1 ));
  8. 8. Reflection is useful for <ul><li>Why reverse engineer comments in code? Easy to generate documentation. </li></ul><ul><li>Unit tests framework: mockup objects, function test*, etc. </li></ul><ul><li>Automatic serializations of object: your code defines your data, your objects can be serialized automatically, converted in JSON, etc. </li></ul>$reflectionClass  = new ReflectionClass( 'ClassIsData' ); $properties = $reflectionClass- >getProperties(); $property ->getName(); $property ->getValue( $instance );
  9. 9. Reflection is useful for <ul><li>Annotations, eg. in PHP Unit </li></ul>In this example the test will fail because it doesn’t throw the InvalidArgumentException
  10. 10. Easy Web Services Simple use case
  11. 11. Watch out, you will see code in slides!!!
  12. 12. class Users { /** * @return array the list of all the users */ static public function getUsers( $limit = 10) { // each API method can have different permission requirements Access::checkUserHasPermission( 'admin' ); return Registry::get( 'db' )->fetchAll( &quot; SELECT * FROM users LIMIT $limit&quot; ); } } Use case: you have this class in your system: You want this class and the public methods to be automatically available in a REST service, so you can call: http://myService.net/?module=Users.getUsers&limit=100 And get the result (eg. in XML)
  13. 13. // simple call to the REST API via http $users = file_get_contents( &quot;http://service/API/&quot; . &quot;?method=Users.getUsers&limit=100&quot; ); // we also want to call it from within our existing php code FrontController::getInstance()->init(); // init DB, logger, auth, etc. $request = new Request( 'method=Users.getUsers&limit=100' ); $result = $request ->process(); How we want to call it (1/2)
  14. 14. // ResponseBuilder object can convert the data in XML, JSON, CSV // by converting your API returned value (from array, int, object, etc) $request = new Request( ' method=Users.getUsers &limit=100 &format=JSON' ); $XmlResult = $request ->process(); // possible to add token_based authentication: all API methods call helper // class that checks that the token has the right permissions $request = new Request( 'method=Users.getUsers&token_auth=puiwrtertwoc98' ); $result = $request ->process(); How we want to call it (2/2)
  15. 15. The concept Request comes in, forwarded to Proxy that does the Reflection magic: calls the method on the right class, with the right parameters mapped.
  16. 16. class Request { protected $request ; function __construct( $requestString = null) { if (is_null( $requestString )) { $request = $_REQUEST ; } else { $request = parse_str( $requestString ); } $this ->request = $request ; } function process() { $responseBuilder = new ResponseBuilder( $this ->request); try { // eg. get the &quot;Users.getUsers&quot; $methodToCall = Helper::sanitizeInputVariable( 'method' , $this ->request); list ( $className , $method ) = e xplode( '.' , $methodToCall ); $proxy = Proxy::getInstance(); $returnedValue = $proxy ->call( $className , $method , $this ->request ); // return the response after applying standard filters, converting format,.. $response = $responseBuilder ->getResponse( $returnedValue ); } catch (Exception $e ) { // exception is forwarded to ResponseBuilder to be converted in XML/JSON,.. $response = $responseBuilder ->getResponseException( $e ); } return $response ; } } $request = new Request( 'method=Users.getUsers&limit=100' ); $result = $request ->process();
  17. 17. class Proxy { function call( $className , $methodName , $request ) { $this->setContext( $className , $methodName , $request); $this ->loadClassMetadata(); $this ->checkMethodExists(); $this ->checkParametersAreSet(); $parameterValues = $this ->getParametersValues(); $object = call_user_func( array ( $className , &quot;getInstance&quot; )); $timer = new Timer; $returnedValue = call_user_func_array( array ( $object , $methodName ), $parameterValues ); Registry::get( 'logger_api' )->log( $className , $methodName , $ parameterValues $timer ->getTimeMs(), $returnedValue) ; return $returnedValue ; } function loadClassMetadata( $className ) { $reflectionClass = new ReflectionClass( $className ); foreach ( $reflectionClass ->getMethods() as $method ) { $this ->loadMethodMetadata( $className , $method ); } } [...] }
  18. 18. Conclusion <ul><li>Similar pattern as FrontController / Dispatcher </li></ul><ul><li>One entry point to your Models. You can then add: </li></ul><ul><ul><li>Caching </li></ul></ul><ul><ul><li>Logging </li></ul></ul><ul><ul><li>Authentication </li></ul></ul><ul><li>Eg. If your app is data-centric, the ResponseBuilder could apply set of filters. You could for example specify custom filters to be apply to API calls in the RequestString: </li></ul>$request = new Request( ' method=Analytics.getUsers &filter_sort=name-desc &filter_search=(pattern)' );
  19. 19. ... and use the Proxy class to generate your API documentation (from the code, and by reverse engineering your method comments)
  20. 20. Questions ?
  21. 21. References <ul><li>This pattern is used in the open source Piwik project http://piwik.org </li></ul><ul><li>View the code on http://dev.piwik.org/svn/trunk/core/API/ </li></ul><ul><li>How to design an API: best practises, concepts http://piwik.org/blog/2008/01/how-to-design-an-api-best-practises-concepts-technical-aspects/ </li></ul><ul><li>PHP: Reflection – Manual http://uk.php.net/oop5.reflection </li></ul><ul><li>Declarative Development Using Annotations In PHP http://www.slideshare.net/stubbles/declarative-development-using-annotations-in-php </li></ul><ul><li>Presentation under license #cc-by-sa, by Matthieu Aubry </li></ul>
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×