Loading...
Flash Player 9 (or above) is needed to view slideshows. We have detected that you do not have it on your computer.To install it, go here
Declarative Development Using Annotations In PHP
Presentation from the International PHP Conference 2007 - Spring Edition
3167 views | comments | 2 favorites | 0 downloads | 6 embeds (Stats)
More Info
This slideshow is Public
Total Views: 3167 on Slideshare: 2866 from embeds: 301
Most viewed embeds (Top 5):
More
Slideshow Transcript
- Slide 1: Declarative Development
using Annotations in PHP
Frank Kleine & Stephan Schmidt
- Slide 2: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
Agenda
• The Speakers
• Basic Concept of Annotations
• Annotations in Java
• Annotations in PHP
• Annotations in Stubbles
• Usage examples
• Defining your own annotations
• Q&A
2
- Slide 3: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
Frank Kleine
• Working at 1&1 Internet Inc.
• PHP since 2000
• Stubbles Lead Developer
• Co-author of \"Exploring PHP\"
3
- Slide 4: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
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
4
- Slide 5: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
The audience?
• Who is using PHP5?
• Who is using object-oriented
development?
• Who is using PHP‘s reflection features?
5
- Slide 6: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
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
6
- Slide 7: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using 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
7
- Slide 8: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
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
8
- Slide 9: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
Annotations in Java 5
• Annotations are part of the language
public @interface MyAnnotation {
String myParam();
}
@MyAnnotation(myParam=\"Foo\")
public class MyClass {}
• Also accessible at runtime
9
- Slide 10: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
Annotations in PHP
Annotations are not part of any PHP
version.
Is this the end of the session?
10
- Slide 11: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
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 {}
11
- Slide 12: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
History of annotations in PHP
1. There was PHPDoc
2. There was PHPDoc
3. PHP 5 was released
4. Some frameworks accessed PHPDoc tags
5. Some frameworks started using some
\"specialized\" doc comments
12
- Slide 13: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
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
13
- Slide 14: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using 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/Extende
dReflectionAPI
14
- Slide 15: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
PHP_Unit
class Calculator {
/**
* @assert (0, 0) == 0
* @assert (1, 0) == 1
* @assert (1, 1) == 2
*/
public function add($a, $b)
{
return $a + $b;
}
}
15
- Slide 16: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
SCA/SDO
class MyApplication {
/**
* The stock quote service to use.
*
* @reference
* @binding.wsdl ../StockQuote/StockQuote.wsdl
*/
public $stock_quote;
...
}
16
- Slide 17: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
More specialized Frameworks
• Services_Webservice makes use of
\"pimped\" PHPDoc comments to create
WSDL
• EZPDO uses annotations to ease object-
relational mapping
17
- Slide 18: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
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
18
- Slide 19: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using 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
19
- Slide 20: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
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/
20
- Slide 21: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
Stubbles
• OOP PHP 5.2 framework
• Package based
• Provides generic annotation functionality
• Eats its own dog food and uses annotations
in various packages
21
- Slide 22: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
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
22
- Slide 23: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
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 ...
}
23
- Slide 24: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
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();
24
- Slide 25: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
The resulting XML
<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>
<Person>
<getId>1</getId>
<getName>schst</getName>
<getAge>33</getAge>
<getRole>admin</getRole>
</Person>
25
- Slide 26: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
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.
26
- Slide 27: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
XMLSerializer annotations
Changing the name of the root tag:
/**
* A person
*
* @XMLTag(tagName=\"user\")
*/
class Person {
... rest of the code ...
}
27
- Slide 28: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
XMLSerializer annotations
Changing the name of other tags
/**
* Get the name
*
* @XMLTag(tagName=\"realname\")
* @return string
*/
public function getName() {
return $this->name;
}
28
- Slide 29: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
XMLSerializer annotations
Using attributes instead of tags
/**
* Get the id
*
* @XMLAttribute(attributeName=\"userId\")
* @return int
*/
public function getId() {
return $this->id;
}
29
- Slide 30: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
XMLSerializer annotations
Ignoring methods
/**
* Get the age
*
* @XMLIgnore
* @return int
*/
public function getAge() {
return $this->age;
}
30
- Slide 31: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
The modified XML
<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>
<user userId=\"1\">
<realname>schst</realname>
<role>admin</role>
</user>
• tag names have been changed
• id property is serialized as attribute
• age is omitted
31
- Slide 32: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
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 \"batch-process\"
methods and properties
32
- Slide 33: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
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 getter and of course setter methods for the other properties ...
}
33
- Slide 34: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
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) ...
34
- Slide 35: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
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
35
- Slide 36: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
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
36
- Slide 37: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
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');
37
- Slide 38: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
Accessing annotations in PHP
PHP's built-in reflection API:
$class = new ReflectionClass('Person');
echo $class->getName() . \"\\n\";
foreach ($class->getMethods() as $method) {
echo \" -> \" . $method->getName() . \"\\n\";
}
Person
-> __construct
-> getId
-> getName
-> ...
38
- Slide 39: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
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
)
39
- Slide 40: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
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
40
- Slide 41: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
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
41
- Slide 42: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
Example: CSV Export
/**
* A person
*
* @CSV(file=\"users.csv\",
* delimeter=\";\")
*/
class Person {
...properties and methods ...
/**
* Get the id
*
* @CSVField
* @return int
*/
public function getId() {
return $this->id;
}
}
42
- Slide 43: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
The @CSV Annotation
class stubCSVAnnotation
extends stubAbstractAnnotation
implements stubAnnotation {
}
43
- Slide 44: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
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
44
- Slide 45: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
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;
}
}
45
- Slide 46: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
Annotation parameter types
• Strings (enclosed in \" or ')
• integers and doubles
• true, false and null
• PHP constants for configurable annotations
• instances of stubReflectionClass
(clazz=Person.class)
46
- Slide 47: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
Annotation targets
• Annotations may be added to
• Classes
• Properties
• Methods
• Functions
• Each annotation may restrict the possible
targets
47
- Slide 48: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
The @CSV Annotation
• Should only be added to classes
class stubCSVAnnotation extends stubAbstractAnnotation
implements stubAnnotation {
public function getAnnotationTarget() {
return stubAnnotation::TARGET_CLASS;
}
}
• Parser will throw an exception on error
48
- Slide 49: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
The @CSVField Annotation
• Can be added to methods and properties
class stubCSVFieldAnnotation
extends stubAbstractAnnotation
implements stubAnnotation {
public function getAnnotationTarget() {
return stubAnnotation::TARGET_METHOD
| stubAnnotation::TARGET_PROPERTY;
}
}
49
- Slide 50: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
Implementing the CSV Writer
1. Accept any object
2. Check for @CSV annotation
3. Extract parameters from annotation
4. Traverse all methods and properties
5. Check for @CSVField annotation
6. Invoke the methods
7. Write line to file
50
- Slide 51: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
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) {
51
- Slide 52: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
The CSVWriter class
if (!$method->hasAnnotation('CSVField')) {
continue;
}
$fields[] = $method->invoke($obj);
}
$line = implode($csv->getDelimeter(), $fields);
fwrite($fp, $line . \"\\n\");
fclose($fp);
}
}
52
- Slide 53: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
Using the CSVWriter class
• Pass any annotated object to the
write() method:
$user = new Person(1, 'schst', 33, 'admin');
CSVWriter::write($user);
users.csv:
1;schst;33
53
- Slide 54: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
Advances Features
• Annotations are cached during and
between the requests
• Annotations can be modified at run-tim
54
- Slide 55: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
Advanced features
Annotations may be interfaces that can be
implemented in various ways:
/**
* @XMLMethods[XMLMatcher](pattern='/^get(.+)/')
*/
class Person {
... methods ...
}
55
- Slide 56: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
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
56
- Slide 57: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
The end
Thank you for your attention.
Want to know more?
http://www.stubbles.net
http://www.frankkleine.de
http://www.schst.net
57
- Slide 58: Frank Kleine & Stephan Schmidt, 1&1 Internet AG
Declarative Development using Annotations
Commercial break
58