SlideShare a Scribd company logo
Declarative Development using Annotations in PHP Frank Kleine & Stephan Schmidt
Agenda The Speakers Basic Concept of Annotations Annotations in Java Annotations in PHP Annotations in Stubbles Usage examples Defining your own annotations Q&A
Frank Kleine Working at 1&1 Internet Inc. PHP since 2000 Stubbles Lead Developer Co-author of "Exploring PHP"
Stephan Schmidt Team Leader at 1&1 Internet Inc. Contributor to the PHP Open Source Community since 2001 15 PEAR packages, 1 pecl extension Author of „PHP Design Patters“ and co-author of several other PHP-related books Speaker at various conferences since 2001
The audience? Who is using PHP5? Who is using object-oriented development? Who is using PHP‘s reflection features?
Basic concept of Annotations Add metadata to classes, methods, properties Do not (directly) affect program semantics Can be used by tools or libraries Can be parameterized or simple marker annotations
Example scenarios Marking classes/methods as accessible via a web service Marking methods as unit test methods Defining how an object should be persisted or serialized Automating dependency injection
Annotations in Java 4 Doclets, similar to PHPDoc Accessible via a Doclet API and a command line tool Not only used for documentation purposes Xdoclet for creation of EJBs and more
Annotations in Java 5 Also accessible at runtime public @interface MyAnnotation { String myParam(); } @MyAnnotation(myParam="Foo") public class MyClass {} Annotations are part of the language
Annotations in PHP Is this the end of the session? Annotations are not part of any PHP version.
Annotations in PHP (revisited) Probably 90% of you used some kind of annotation /** * My class * *  @author The Stubbles Team *  @see http://www.stubbles.net */ class MyClass {}
History of annotations in PHP There was PHPDoc There was PHPDoc PHP 5 was released Some frameworks accessed PHPDoc tags Some frameworks started using some "specialized" doc comments
Specialized frameworks Annotations embedded in DocBlocks Allow you to use annotations supported by the framework. No generic parser for annotations, but mostly some regexps Not (easily) possible to include new annotations
Extended Reflection API Provides access to PHPDoc comments Used to get information about the types of parameters or properties No real annotation support http://instantsvc.toolslave.net/wiki/ExtendedReflectionAPI
PHP_Unit class Calculator { /** *  @assert (0, 0) == 0 *  @assert (1, 0) == 1 *  @assert (1, 1) == 2 */ public function add($a, $b) { return $a + $b; } }
SCA/SDO class MyApplication { /** * The stock quote service to use. * *  @reference *  @binding.wsdl ../StockQuote/StockQuote.wsdl */ public $stock_quote; ... }
More specialized Frameworks Services_Webservice makes use of "pimped" PHPDoc comments to create WSDL EZPDO uses annotations to ease object-relational mapping
Next step: Generic frameworks Enable you to create your own annotations Provide generic annotation parsers Provide access to annotations at run-time No common standard for annotations
PEAR::PHP_Annotation Parser for generic DocBlocks and Java-style annotations Provides mechanism for dependency injection No public release, yet First and last commit 4 months ago
Addendum Supports Java-style annotations Annotations are classes that extend class  Annotation Annotations are accessible via reflection classes that extend built-in reflection http://code.google.com/p/addendum/
Stubbles OOP PHP 5.2 framework Package based Provides generic annotation functionality Eats its own dog food and uses annotations in various packages
Annotations in Stubbles Persistence Serializing objects to XML Persisting objects in RDMBS Security Marking methods as callable via JSON-RPC Marking methods callable from XSLT Misc Managing dependency injection
A Person POPO class Person { protected $id; protected $name; protected $age; protected $role; public function __construct($id, $name, $age, $role = 'user') { $this->id  = $id; $this->name = $name; $this->age  = $age; $this->role = $role; } public function getId() { return $this->id; } ... more getter methods for the other properties ... }
Serializing to XML // Create a serializer $serializer = new stubXMLSerializer(); // XML in Stubbles is created via a streaming API $writer = stubXMLStreamWriterFactory::createAsAvailable(); // Create and serialize the object $user = new Person (1, 'schst', 33, 'admin'); $serializer->serialize($user, $writer); echo writer->asXML();
The resulting XML <?xml version=&quot;1.0&quot; encoding=&quot;ISO-8859-1&quot;?> < Person > < getId >1</ getId > < getName >schst</ getName > < getAge >33</ getAge > < getRole >admin</ getRole > </ Person >
XMLSerializer behaviour All public methods without parameters are exported Class and method names are used as tag names But:  The behavior can be changed by annotating the class.
XMLSerializer annotations Changing the name of the root tag: /** * A person * *  @XMLTag(tagName=&quot;user&quot;) */ class Person { ... rest of the code ... }
XMLSerializer annotations Changing the name of other tags /** * Get the name * *  @XMLTag(tagName=&quot;realname&quot;) * @return string */ public function getName() { return $this->name; }
XMLSerializer annotations Using attributes instead of tags /** * Get the id * *  @XMLAttribute(attributeName=&quot;userId&quot;) * @return int */ public function getId() { return $this->id; }
XMLSerializer annotations Ignoring methods /** * Get the age * *  @XMLIgnore * @return int */ public function getAge() { return $this->age; }
The modified XML <?xml version=&quot;1.0&quot; encoding=&quot;ISO-8859-1&quot;?> < user   userId=&quot;1&quot; > < realname >schst</ realname > < role >admin</ role > </ user > tag names have been changed id property is serialized as attribute age is omitted
Features of XMLSerializer Serializes (nearly) every data structure Able to use ext/dom or ext/xmlwriter Able to serialize public methods and properties Provides annotations to &quot;batch-process&quot; methods and properties
Persistence: POPO revisited /** * @DBTable(name='persons') ‏ */ class Person  extends stubAbstractPersistable  { ... properties like in old version ... /** * @DBColumn(name='person_id', isPrimaryKey=true) ‏ */ public function getId() { return $this->id; } } /** * @DBColumn(name='name', defaultValue='') ‏ */ public function getName() { return $this->name; } /** * @DBColumn(name='age', defaultValue=0) ‏ */ public function getAge() { return $this->age; } ... more ge tte r and of course setter methods for the other properties ... }
Persistence: insert ... create the person with the data ... $person = new Person(); $person->setName('Frank Kleine'); $person->setAge(27); $person->setRole('admin'); ... get the connection ... $connection = stubDatabaseConnectionPool::getConnection(); ... get the serializer ... $serializer = stubDatabaseSerializer::getInstance($connection); ... and save to database ... $serializer->serialize($person); ... done: ... var_dump($person->getId()); ... displays int(1) ...
Persistence: select (find) ‏ ... create the person object ... $person = new Person(); $person->setId(1); ... get the connection ... $connection = stubDatabaseConnectionPool::getConnection(); ... get the finder ... $finder = stubDatabaseFinder::getInstance($connection); ... and retrieve data ... $finder->findByPrimaryKeys($person); ... done: ... var_dump($person->getAge()); ... displays int(27) ... or: $criterion = new stubEqualCriterion('age', 27); $persons = $finder->findByCriterion($criterion, 'Person'); ... $persons is now an array containing a list of Person objects all of age 27
Persistence: more features Delete similarly to finder Update works like insert Very simple support for joins (needs more research) ‏ Independent of database: connection handle knows database type, correct query builder is selected
Persistence: going crazy /** * @DBTable(name='persons', type='InnoDB') ‏ */ class Person  extends stubAbstractPersistable  { ... properties like in old version ... /** * @DBColumn(name='person_id', isPrimaryKey=true, type='int', size=10, isUnsigned=true) ‏ */ public function getId() { return $this->id; } } /** * @DBColumn(name='name', defaultValue='', type='varchar', size=255, isNullable=false) ‏ */ public function getName() { return $this->name; } } $connection = stubDatabaseConnectionPool::getConnection(); $creator = stubDatabaseCreator::getInstance($connection); $creator->createTable('Person');
Accessing annotations in PHP PHP's built-in reflection API: $class = new ReflectionClass('Person'); echo $class->getName() . &quot;\n&quot;; foreach ($class->getMethods() as $method) { echo &quot; -> &quot; . $method->getName()  . &quot;\n&quot;; } Person -> __construct -> getId -> getName -> ...
Accessing annotations in PHP Stubbles' reflection API: $class = new  stubReflectionClass ('Person'); if ($class-> hasAnnotation ('XMLTag')) { $xmlTag = $class-> getAnnotation ('XMLTag'); print_r($xmlTag); } stubXMLTagAnnotation Object ( [tagName:protected] => user [elementTagName:protected] => [annotationName:protected] => XMLTag )
Stubbles' reflection Provides drop-in replacements for all built-in reflection classes, that extend the built-in classes (for type safety) Provides two additional methods: hasAnnotation(string name) getAnnotation(string name) Annotations are objects
Creating annotations Annotation classes must implement  stubAnnotation  interface Annotations can extend abstract base class Annotations should comply to naming scheme Annotations may contain additional properties and methods
Example: CSV Export /** * A person * *  @CSV(file=&quot;users.csv&quot;, *  delimeter=&quot;;&quot;) */ class Person { ...properties and methods ... /** * Get the id * *  @CSVField * @return int */ public function getId() { return $this->id; } }
The  @CSV  Annotation class stubCSVAnnotation extends  stubAbstractAnnotation implements  stubAnnotation  { }
Annotation parameters Parameters can be set in three ways Providing a public property with the same name as the parameter Providing a public method with the same name as the parameter prefixed with  set Providing a magic  __set()  method
The  @CSV  Annotation class stubCSVAnnotation extends stubAbstractAnnotation implements stubAnnotation { public $file ; protected $delimeter; public function setDelimeter($delim) { $this->delimeter = $delim; } public function getDelimeter() { return $this->delimeter; } }
Annotation parameter types Strings (enclosed in &quot; or ') integers and doubles true ,  false  and  null PHP constants for configurable annotations instances of stubReflectionClass ( clazz=Person.class )
Annotation targets Annotations may be added to Classes Properties Methods Functions Each annotation may restrict the possible targets
The  @CSV  Annotation class stubCSVAnnotation extends stubAbstractAnnotation implements stubAnnotation { public function getAnnotationTarget() { return stubAnnotation::TARGET_CLASS; } } Should only be added to classes Parser will throw an exception on error
The  @CSVField  Annotation class stubCSVFieldAnnotation extends stubAbstractAnnotation implements stubAnnotation { public function getAnnotationTarget() { return stubAnnotation::TARGET_METHOD | stubAnnotation::TARGET_PROPERTY; } } Can be added to methods and properties
Implementing the CSV Writer Accept any object Check for  @CSV  annotation Extract parameters from annotation Traverse all methods and properties Check for  @CSVField  annotation Invoke the methods Write line to file
The  CSVWriter  class class CSVWriter { public static function write($obj) { $class = new stubReflectionClass(get_class($obj)); if (! $class->hasAnnotation('CSV') ) { throw new Exception('Not suported'); } $csv =  $class->getAnnotation('CSV'); $fp = fopen( $csv->file , 'a'); $fields = array(); foreach ($class->getMethods() as $method) {
The  CSVWriter  class if (! $method->hasAnnotation('CSVField') ) { continue; } $fields[] = $method->invoke($obj); } $line = implode( $csv->getDelimeter() , $fields); fwrite($fp, $line . &quot;\n&quot;); fclose($fp); } }
Using the  CSVWriter  class $user = new Person(1, 'schst', 33, 'admin'); CSVWriter::write($user); users.csv: 1;schst;33 Pass any annotated object to the  write()  method:
Advances Features Annotations are cached during and between the requests Annotations can be modified at run-tim
Advanced features Annotations may be interfaces that can be implemented in various ways: /** *  @XMLMethods [XMLMatcher] (pattern='/^get(.+)/') */ class Person { ... methods ... }
Annotation interfaces XMLSerializer only knows about the  @XMLMethods  annotation interface XMLMatcher  implements this interface and decides which methods to export Annotations do not only provide meta information, but also logic
The end Thank you for your attention. Want to know more? http://www.stubbles.net http://www.frankkleine.de http://www.schst.net
Commercial break

More Related Content

PPT
Scorware - Spring Introduction
PPT
Go OO! - Real-life Design Patterns in PHP 5
PDF
EmberConf 2021 - Crossfile Codemodding with Joshua Lawrence
PPT
XML Transformations With PHP
KEY
Test-Driven Development of Xtext DSLs
PPT
The Big Documentation Extravaganza
ODP
Using DAOs without implementing them
PPT
Component and Event-Driven Architectures in PHP
Scorware - Spring Introduction
Go OO! - Real-life Design Patterns in PHP 5
EmberConf 2021 - Crossfile Codemodding with Joshua Lawrence
XML Transformations With PHP
Test-Driven Development of Xtext DSLs
The Big Documentation Extravaganza
Using DAOs without implementing them
Component and Event-Driven Architectures in PHP

What's hot (19)

PPT
Session Server - Maintaing State between several Servers
PDF
Metaprogramming
PDF
Code generating beans in Java
PPT
Inroduction to XSLT with PHP4
PDF
Xtext's new Formatter API
PDF
Textual Modeling Framework Xtext
ODP
Object Oriented Design Patterns for PHP
PPT
Ruby For Java Programmers
PPT
PDF Localization
PPT
Apache Persistence Layers
ODP
Dynamic Python
ODP
Introduce Django
PPT
PEAR For The Masses
PPTX
PDF
Python in 90 minutes
PDF
Scoping Tips and Tricks
PPT
XML and Web Services with PHP5 and PEAR
PPTX
Dost.jar and fo.jar
PDF
Executable specifications for xtext
Session Server - Maintaing State between several Servers
Metaprogramming
Code generating beans in Java
Inroduction to XSLT with PHP4
Xtext's new Formatter API
Textual Modeling Framework Xtext
Object Oriented Design Patterns for PHP
Ruby For Java Programmers
PDF Localization
Apache Persistence Layers
Dynamic Python
Introduce Django
PEAR For The Masses
Python in 90 minutes
Scoping Tips and Tricks
XML and Web Services with PHP5 and PEAR
Dost.jar and fo.jar
Executable specifications for xtext
Ad

Similar to Declarative Development Using Annotations In PHP (20)

PPT
Processing XML with Java
PPT
Pxb For Yapc2008
PPT
WordPress development paradigms, idiosyncrasies and other big words
PDF
Python RESTful webservices with Python: Flask and Django solutions
PPT
PDF
Take the Plunge with OOP from #pnwphp
PDF
Ejb3 Struts Tutorial En
PDF
Ejb3 Struts Tutorial En
ODP
Exploring Symfony's Code
PPT
RESTful Services
PPT
Bioinformatica 10-11-2011-p6-bioperl
PPT
Smoothing Your Java with DSLs
PPT
Security.ppt
PPT
12-security.ppt - PHP and Arabic Language - Index
PPT
Boost Your Environment With XMLDB - UKOUG 2008 - Marco Gralike
PPSX
Symfony2 meets propel 1.5
PPT
Architecture | Busy Java Developers Guide to NoSQL | Ted Neward
PDF
Demystifying Object-Oriented Programming #ssphp16
PDF
OOP in PHP
PPT
Introduction to PHP
Processing XML with Java
Pxb For Yapc2008
WordPress development paradigms, idiosyncrasies and other big words
Python RESTful webservices with Python: Flask and Django solutions
Take the Plunge with OOP from #pnwphp
Ejb3 Struts Tutorial En
Ejb3 Struts Tutorial En
Exploring Symfony's Code
RESTful Services
Bioinformatica 10-11-2011-p6-bioperl
Smoothing Your Java with DSLs
Security.ppt
12-security.ppt - PHP and Arabic Language - Index
Boost Your Environment With XMLDB - UKOUG 2008 - Marco Gralike
Symfony2 meets propel 1.5
Architecture | Busy Java Developers Guide to NoSQL | Ted Neward
Demystifying Object-Oriented Programming #ssphp16
OOP in PHP
Introduction to PHP
Ad

Recently uploaded (20)

PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PPTX
Spectroscopy.pptx food analysis technology
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
PDF
Approach and Philosophy of On baking technology
PDF
Empathic Computing: Creating Shared Understanding
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PDF
NewMind AI Weekly Chronicles - August'25-Week II
PPTX
A Presentation on Artificial Intelligence
PDF
Review of recent advances in non-invasive hemoglobin estimation
PDF
A comparative analysis of optical character recognition models for extracting...
PDF
Encapsulation theory and applications.pdf
PDF
Network Security Unit 5.pdf for BCA BBA.
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Digital-Transformation-Roadmap-for-Companies.pptx
Building Integrated photovoltaic BIPV_UPV.pdf
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Spectroscopy.pptx food analysis technology
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Per capita expenditure prediction using model stacking based on satellite ima...
Spectral efficient network and resource selection model in 5G networks
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
Approach and Philosophy of On baking technology
Empathic Computing: Creating Shared Understanding
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
MIND Revenue Release Quarter 2 2025 Press Release
NewMind AI Weekly Chronicles - August'25-Week II
A Presentation on Artificial Intelligence
Review of recent advances in non-invasive hemoglobin estimation
A comparative analysis of optical character recognition models for extracting...
Encapsulation theory and applications.pdf
Network Security Unit 5.pdf for BCA BBA.

Declarative Development Using Annotations In PHP

  • 1. Declarative Development using Annotations in PHP Frank Kleine & Stephan Schmidt
  • 2. Agenda The Speakers Basic Concept of Annotations Annotations in Java Annotations in PHP Annotations in Stubbles Usage examples Defining your own annotations Q&A
  • 3. Frank Kleine Working at 1&1 Internet Inc. PHP since 2000 Stubbles Lead Developer Co-author of &quot;Exploring PHP&quot;
  • 4. Stephan Schmidt Team Leader at 1&1 Internet Inc. Contributor to the PHP Open Source Community since 2001 15 PEAR packages, 1 pecl extension Author of „PHP Design Patters“ and co-author of several other PHP-related books Speaker at various conferences since 2001
  • 5. The audience? Who is using PHP5? Who is using object-oriented development? Who is using PHP‘s reflection features?
  • 6. Basic concept of Annotations Add metadata to classes, methods, properties Do not (directly) affect program semantics Can be used by tools or libraries Can be parameterized or simple marker annotations
  • 7. Example scenarios Marking classes/methods as accessible via a web service Marking methods as unit test methods Defining how an object should be persisted or serialized Automating dependency injection
  • 8. Annotations in Java 4 Doclets, similar to PHPDoc Accessible via a Doclet API and a command line tool Not only used for documentation purposes Xdoclet for creation of EJBs and more
  • 9. Annotations in Java 5 Also accessible at runtime public @interface MyAnnotation { String myParam(); } @MyAnnotation(myParam=&quot;Foo&quot;) public class MyClass {} Annotations are part of the language
  • 10. Annotations in PHP Is this the end of the session? Annotations are not part of any PHP version.
  • 11. Annotations in PHP (revisited) Probably 90% of you used some kind of annotation /** * My class * * @author The Stubbles Team * @see http://www.stubbles.net */ class MyClass {}
  • 12. History of annotations in PHP There was PHPDoc There was PHPDoc PHP 5 was released Some frameworks accessed PHPDoc tags Some frameworks started using some &quot;specialized&quot; doc comments
  • 13. Specialized frameworks Annotations embedded in DocBlocks Allow you to use annotations supported by the framework. No generic parser for annotations, but mostly some regexps Not (easily) possible to include new annotations
  • 14. Extended Reflection API Provides access to PHPDoc comments Used to get information about the types of parameters or properties No real annotation support http://instantsvc.toolslave.net/wiki/ExtendedReflectionAPI
  • 15. PHP_Unit class Calculator { /** * @assert (0, 0) == 0 * @assert (1, 0) == 1 * @assert (1, 1) == 2 */ public function add($a, $b) { return $a + $b; } }
  • 16. SCA/SDO class MyApplication { /** * The stock quote service to use. * * @reference * @binding.wsdl ../StockQuote/StockQuote.wsdl */ public $stock_quote; ... }
  • 17. More specialized Frameworks Services_Webservice makes use of &quot;pimped&quot; PHPDoc comments to create WSDL EZPDO uses annotations to ease object-relational mapping
  • 18. Next step: Generic frameworks Enable you to create your own annotations Provide generic annotation parsers Provide access to annotations at run-time No common standard for annotations
  • 19. PEAR::PHP_Annotation Parser for generic DocBlocks and Java-style annotations Provides mechanism for dependency injection No public release, yet First and last commit 4 months ago
  • 20. Addendum Supports Java-style annotations Annotations are classes that extend class Annotation Annotations are accessible via reflection classes that extend built-in reflection http://code.google.com/p/addendum/
  • 21. Stubbles OOP PHP 5.2 framework Package based Provides generic annotation functionality Eats its own dog food and uses annotations in various packages
  • 22. Annotations in Stubbles Persistence Serializing objects to XML Persisting objects in RDMBS Security Marking methods as callable via JSON-RPC Marking methods callable from XSLT Misc Managing dependency injection
  • 23. A Person POPO class Person { protected $id; protected $name; protected $age; protected $role; public function __construct($id, $name, $age, $role = 'user') { $this->id = $id; $this->name = $name; $this->age = $age; $this->role = $role; } public function getId() { return $this->id; } ... more getter methods for the other properties ... }
  • 24. Serializing to XML // Create a serializer $serializer = new stubXMLSerializer(); // XML in Stubbles is created via a streaming API $writer = stubXMLStreamWriterFactory::createAsAvailable(); // Create and serialize the object $user = new Person (1, 'schst', 33, 'admin'); $serializer->serialize($user, $writer); echo writer->asXML();
  • 25. The resulting XML <?xml version=&quot;1.0&quot; encoding=&quot;ISO-8859-1&quot;?> < Person > < getId >1</ getId > < getName >schst</ getName > < getAge >33</ getAge > < getRole >admin</ getRole > </ Person >
  • 26. XMLSerializer behaviour All public methods without parameters are exported Class and method names are used as tag names But: The behavior can be changed by annotating the class.
  • 27. XMLSerializer annotations Changing the name of the root tag: /** * A person * * @XMLTag(tagName=&quot;user&quot;) */ class Person { ... rest of the code ... }
  • 28. XMLSerializer annotations Changing the name of other tags /** * Get the name * * @XMLTag(tagName=&quot;realname&quot;) * @return string */ public function getName() { return $this->name; }
  • 29. XMLSerializer annotations Using attributes instead of tags /** * Get the id * * @XMLAttribute(attributeName=&quot;userId&quot;) * @return int */ public function getId() { return $this->id; }
  • 30. XMLSerializer annotations Ignoring methods /** * Get the age * * @XMLIgnore * @return int */ public function getAge() { return $this->age; }
  • 31. The modified XML <?xml version=&quot;1.0&quot; encoding=&quot;ISO-8859-1&quot;?> < user userId=&quot;1&quot; > < realname >schst</ realname > < role >admin</ role > </ user > tag names have been changed id property is serialized as attribute age is omitted
  • 32. Features of XMLSerializer Serializes (nearly) every data structure Able to use ext/dom or ext/xmlwriter Able to serialize public methods and properties Provides annotations to &quot;batch-process&quot; methods and properties
  • 33. Persistence: POPO revisited /** * @DBTable(name='persons') ‏ */ class Person extends stubAbstractPersistable { ... properties like in old version ... /** * @DBColumn(name='person_id', isPrimaryKey=true) ‏ */ public function getId() { return $this->id; } } /** * @DBColumn(name='name', defaultValue='') ‏ */ public function getName() { return $this->name; } /** * @DBColumn(name='age', defaultValue=0) ‏ */ public function getAge() { return $this->age; } ... more ge tte r and of course setter methods for the other properties ... }
  • 34. Persistence: insert ... create the person with the data ... $person = new Person(); $person->setName('Frank Kleine'); $person->setAge(27); $person->setRole('admin'); ... get the connection ... $connection = stubDatabaseConnectionPool::getConnection(); ... get the serializer ... $serializer = stubDatabaseSerializer::getInstance($connection); ... and save to database ... $serializer->serialize($person); ... done: ... var_dump($person->getId()); ... displays int(1) ...
  • 35. Persistence: select (find) ‏ ... create the person object ... $person = new Person(); $person->setId(1); ... get the connection ... $connection = stubDatabaseConnectionPool::getConnection(); ... get the finder ... $finder = stubDatabaseFinder::getInstance($connection); ... and retrieve data ... $finder->findByPrimaryKeys($person); ... done: ... var_dump($person->getAge()); ... displays int(27) ... or: $criterion = new stubEqualCriterion('age', 27); $persons = $finder->findByCriterion($criterion, 'Person'); ... $persons is now an array containing a list of Person objects all of age 27
  • 36. Persistence: more features Delete similarly to finder Update works like insert Very simple support for joins (needs more research) ‏ Independent of database: connection handle knows database type, correct query builder is selected
  • 37. Persistence: going crazy /** * @DBTable(name='persons', type='InnoDB') ‏ */ class Person extends stubAbstractPersistable { ... properties like in old version ... /** * @DBColumn(name='person_id', isPrimaryKey=true, type='int', size=10, isUnsigned=true) ‏ */ public function getId() { return $this->id; } } /** * @DBColumn(name='name', defaultValue='', type='varchar', size=255, isNullable=false) ‏ */ public function getName() { return $this->name; } } $connection = stubDatabaseConnectionPool::getConnection(); $creator = stubDatabaseCreator::getInstance($connection); $creator->createTable('Person');
  • 38. Accessing annotations in PHP PHP's built-in reflection API: $class = new ReflectionClass('Person'); echo $class->getName() . &quot;\n&quot;; foreach ($class->getMethods() as $method) { echo &quot; -> &quot; . $method->getName() . &quot;\n&quot;; } Person -> __construct -> getId -> getName -> ...
  • 39. Accessing annotations in PHP Stubbles' reflection API: $class = new stubReflectionClass ('Person'); if ($class-> hasAnnotation ('XMLTag')) { $xmlTag = $class-> getAnnotation ('XMLTag'); print_r($xmlTag); } stubXMLTagAnnotation Object ( [tagName:protected] => user [elementTagName:protected] => [annotationName:protected] => XMLTag )
  • 40. Stubbles' reflection Provides drop-in replacements for all built-in reflection classes, that extend the built-in classes (for type safety) Provides two additional methods: hasAnnotation(string name) getAnnotation(string name) Annotations are objects
  • 41. Creating annotations Annotation classes must implement stubAnnotation interface Annotations can extend abstract base class Annotations should comply to naming scheme Annotations may contain additional properties and methods
  • 42. Example: CSV Export /** * A person * * @CSV(file=&quot;users.csv&quot;, * delimeter=&quot;;&quot;) */ class Person { ...properties and methods ... /** * Get the id * * @CSVField * @return int */ public function getId() { return $this->id; } }
  • 43. The @CSV Annotation class stubCSVAnnotation extends stubAbstractAnnotation implements stubAnnotation { }
  • 44. Annotation parameters Parameters can be set in three ways Providing a public property with the same name as the parameter Providing a public method with the same name as the parameter prefixed with set Providing a magic __set() method
  • 45. The @CSV Annotation class stubCSVAnnotation extends stubAbstractAnnotation implements stubAnnotation { public $file ; protected $delimeter; public function setDelimeter($delim) { $this->delimeter = $delim; } public function getDelimeter() { return $this->delimeter; } }
  • 46. Annotation parameter types Strings (enclosed in &quot; or ') integers and doubles true , false and null PHP constants for configurable annotations instances of stubReflectionClass ( clazz=Person.class )
  • 47. Annotation targets Annotations may be added to Classes Properties Methods Functions Each annotation may restrict the possible targets
  • 48. The @CSV Annotation class stubCSVAnnotation extends stubAbstractAnnotation implements stubAnnotation { public function getAnnotationTarget() { return stubAnnotation::TARGET_CLASS; } } Should only be added to classes Parser will throw an exception on error
  • 49. The @CSVField Annotation class stubCSVFieldAnnotation extends stubAbstractAnnotation implements stubAnnotation { public function getAnnotationTarget() { return stubAnnotation::TARGET_METHOD | stubAnnotation::TARGET_PROPERTY; } } Can be added to methods and properties
  • 50. Implementing the CSV Writer Accept any object Check for @CSV annotation Extract parameters from annotation Traverse all methods and properties Check for @CSVField annotation Invoke the methods Write line to file
  • 51. The CSVWriter class class CSVWriter { public static function write($obj) { $class = new stubReflectionClass(get_class($obj)); if (! $class->hasAnnotation('CSV') ) { throw new Exception('Not suported'); } $csv = $class->getAnnotation('CSV'); $fp = fopen( $csv->file , 'a'); $fields = array(); foreach ($class->getMethods() as $method) {
  • 52. The CSVWriter class if (! $method->hasAnnotation('CSVField') ) { continue; } $fields[] = $method->invoke($obj); } $line = implode( $csv->getDelimeter() , $fields); fwrite($fp, $line . &quot;\n&quot;); fclose($fp); } }
  • 53. Using the CSVWriter class $user = new Person(1, 'schst', 33, 'admin'); CSVWriter::write($user); users.csv: 1;schst;33 Pass any annotated object to the write() method:
  • 54. Advances Features Annotations are cached during and between the requests Annotations can be modified at run-tim
  • 55. Advanced features Annotations may be interfaces that can be implemented in various ways: /** * @XMLMethods [XMLMatcher] (pattern='/^get(.+)/') */ class Person { ... methods ... }
  • 56. Annotation interfaces XMLSerializer only knows about the @XMLMethods annotation interface XMLMatcher implements this interface and decides which methods to export Annotations do not only provide meta information, but also logic
  • 57. The end Thank you for your attention. Want to know more? http://www.stubbles.net http://www.frankkleine.de http://www.schst.net