Rafael����������� ������������������ Dohms
Annotations����������� ������������������ in����������� ������������������ PHP
@rdohmson����������� ������������������ twitter
They����������� ������������������ Exist!
phot
o cr
edit:
Eli W
hite
Evangelist, Speaker and Contributor.
!Enabler at AmsterdamPHP.
Rafael Dohms@rdohms
drop����������� ������������������ by����������� ������������������ if����������� ������������������ you����������� ������������������ are����������� ������������������ in����������� ������������������ Amsterdam!
What? Why? Where?
How?
a����������� ������������������ little����������� ������������������ history
show����������� ������������������ me����������� ������������������ the����������� ������������������ code!
existing����������� ������������������ uses
Implementing����������� ������������������ custom����������� ������������������ annotations
based����������� ������������������ on����������� ������������������ DMS\Filter
what?What����������� ������������������ ar
e����������� ������������������ annotation
s?
http://ecdesignrebels.blogspot.com
-- In English -- "An annotation is a note that is made while
reading any form of text."
-- In English -- "An annotation is a note that is made while
reading any form of text."
something����������� ������������������ that����������� ������������������ describes����������� ������������������ an����������� ������������������ aspect����������� ������������������ of����������� ������������������ the����������� ������������������ subject
“Annotations do not directly affect program semantics”
-- In Code Speak --
“An annotation is metadata attached to your code, that can be read at runtime.”
“Annotations do not directly affect program semantics”
-- In Code Speak --
“An annotation is metadata attached to your code, that can be read at runtime.”
effects����������� ������������������ are����������� ������������������ only����������� ������������������ observed����������� ������������������ at
“Annotations do not directly affect program semantics”
-- In Code Speak --
just����������� ������������������ like����������� ������������������ your����������� ������������������ notes
“An annotation is metadata attached to your code, that can be read at runtime.”
effects����������� ������������������ are����������� ������������������ only����������� ������������������ observed����������� ������������������ at
Annotations in the wild
C#
Annotations in the wild
annotations
C#attributes
Annotations in the wild
annotations
C#attributes
@Entity! @Table(name = "people")! class Person implements Serializable {! @Id ! @GeneratedValue(strategy = GenerationType.AUTO) ! private Integer id;
Annotations in the wild
annotations
C#attributes
@Entity! @Table(name = "people")! class Person implements Serializable {! @Id ! @GeneratedValue(strategy = GenerationType.AUTO) ! private Integer id;
public class Customer!{! [Required]! [StringLength(50)]! public string Prename { get; set; }! ! [Column(TypeName = "image")]! public byte[] Image { get; set; }
Annotations in the wild
annotations
C#attributes
after����������� ������������������ v1.5
@Entity! @Table(name = "people")! class Person implements Serializable {! @Id ! @GeneratedValue(strategy = GenerationType.AUTO) ! private Integer id;
public class Customer!{! [Required]! [StringLength(50)]! public string Prename { get; set; }! ! [Column(TypeName = "image")]! public byte[] Image { get; set; }
Annotations in the wild
annotations
C#attributes
after����������� ������������������ v1.5
since����������� ������������������ first����������� ������������������ release
@Entity! @Table(name = "people")! class Person implements Serializable {! @Id ! @GeneratedValue(strategy = GenerationType.AUTO) ! private Integer id;
public class Customer!{! [Required]! [StringLength(50)]! public string Prename { get; set; }! ! [Column(TypeName = "image")]! public byte[] Image { get; set; }
No����������� ������������������ core����������� ������������������ ����������� ������������������ annotation����������� ������������������ support
Questions?
Questions?
I’m����������� ������������������ kidding!
phpDoc
~2000
phpDoc
PHP����������� ������������������ 5.1Reflection����������� ������������������ supports����������� ������������������ getDocComments()
~2000 2005
First����������� ������������������ Annotation����������� ������������������
����������� ������������������ Engines����������� ������������������ in����������� ������������������ PHP
phpDoc
PHP����������� ������������������ 5.1Reflection����������� ������������������ supports����������� ������������������ getDocComments()
~2000 2005
First����������� ������������������ Annotation����������� ������������������
����������� ������������������ Engines����������� ������������������ in����������� ������������������ PHP
phpDoc
PHP����������� ������������������ 5.1Reflection����������� ������������������ supports����������� ������������������ getDocComments()
~2000 2005 2008
First����������� ������������������ Annotation����������� ������������������
����������� ������������������ Engines����������� ������������������ in����������� ������������������ PHP
phpDoc
PHP����������� ������������������ 5.1Reflection����������� ������������������ supports����������� ������������������ getDocComments()
~2000 2005 2008
Doctrine����������� ������������������ 2����������� ������������������ Annotation����������� ������������������ Engine
First����������� ������������������ Annotation����������� ������������������
����������� ������������������ Engines����������� ������������������ in����������� ������������������ PHP
phpDoc
PHP����������� ������������������ 5.1Reflection����������� ������������������ supports����������� ������������������ getDocComments()
~2000 2005 2008
Doctrine����������� ������������������ 2����������� ������������������ Annotation����������� ������������������ Engine
2010
RFC:����������� ������������������ Annotations����������� ������������������ in����������� ������������������ core����������� ������������������ w/����������� ������������������ custom����������� ������������������
syntax
First����������� ������������������ Annotation����������� ������������������
����������� ������������������ Engines����������� ������������������ in����������� ������������������ PHP
phpDoc
PHP����������� ������������������ 5.1Reflection����������� ������������������ supports����������� ������������������ getDocComments()
~2000 2005 2008
Doctrine����������� ������������������ 2����������� ������������������ Annotation����������� ������������������ Engine
2010
RFC:����������� ������������������ Annotations����������� ������������������ in����������� ������������������ core����������� ������������������ w/����������� ������������������ custom����������� ������������������
syntaxREJECTED
First����������� ������������������ Annotation����������� ������������������
����������� ������������������ Engines����������� ������������������ in����������� ������������������ PHP
phpDoc
PHP����������� ������������������ 5.1Reflection����������� ������������������ supports����������� ������������������ getDocComments()
~2000 2005 2008
Doctrine����������� ������������������ 2����������� ������������������ Annotation����������� ������������������ Engine
2010
RFC:����������� ������������������ Annotations����������� ������������������ in����������� ������������������ core����������� ������������������ w/����������� ������������������ custom����������� ������������������
syntax
2011
RFC:����������� ������������������ DocBlock����������� ������������������ Annotations����������� ������������������
“in����������� ������������������ discussion”
REJECTED
First����������� ������������������ Annotation����������� ������������������
����������� ������������������ Engines����������� ������������������ in����������� ������������������ PHP
phpDoc
PHP����������� ������������������ 5.1Reflection����������� ������������������ supports����������� ������������������ getDocComments()
~2000 2005 2008
Doctrine����������� ������������������ 2����������� ������������������ Annotation����������� ������������������ Engine
2010
RFC:����������� ������������������ Annotations����������� ������������������ in����������� ������������������ core����������� ������������������ w/����������� ������������������ custom����������� ������������������
syntax
2011
RFC:����������� ������������������ DocBlock����������� ������������������ Annotations����������� ������������������
“in����������� ������������������ discussion”
REJECTED
2013
discussion����������� ������������������ sparks����������� ������������������ up����������� ������������������ again
First����������� ������������������ Annotation����������� ������������������
����������� ������������������ Engines����������� ������������������ in����������� ������������������ PHP
phpDoc
PHP����������� ������������������ 5.1Reflection����������� ������������������ supports����������� ������������������ getDocComments()
~2000 2005 2008
Doctrine����������� ������������������ 2����������� ������������������ Annotation����������� ������������������ Engine
2010
RFC:����������� ������������������ Annotations����������� ������������������ in����������� ������������������ core����������� ������������������ w/����������� ������������������ custom����������� ������������������
syntax
2011
RFC:����������� ������������������ DocBlock����������� ������������������ Annotations����������� ������������������
“in����������� ������������������ discussion”
REJECTED
?2013
discussion����������� ������������������ sparks����������� ������������������ up����������� ������������������ again
Current situation in php-internals
Current situation in php-internals
annotations
annotations
/** ! * Entity\Reward ! * ! * @ORM\Table("reward") ! * @ORM\Entity(repositoryClass="RewardRepository") ! */ !class Reward !{ ! /** ! * @var integer $id ! * ! * @ORM\Column(name="id", type="integer") ! * @ORM\Id ! * @ORM\GeneratedValue(strategy="AUTO") ! */ ! protected $id; ! ! /** ! * @var string $title ! * ! * @ORM\Column(name="title", type="string", length=150, nullable=true) ! * ! * @Assert\MaxLength(150) ! */ ! protected $title;
annotations
/** ! * Entity\Reward ! * ! * @ORM\Table("reward") ! * @ORM\Entity(repositoryClass="RewardRepository") ! */ !class Reward !{ ! /** ! * @var integer $id ! * ! * @ORM\Column(name="id", type="integer") ! * @ORM\Id ! * @ORM\GeneratedValue(strategy="AUTO") ! */ ! protected $id; ! ! /** ! * @var string $title ! * ! * @ORM\Column(name="title", type="string", length=150, nullable=true) ! * ! * @Assert\MaxLength(150) ! */ ! protected $title;
re-use����������� ������������������ of����������� ������������������ docblocks
On docblocks vs. comments
On docblocks vs. comments
T_COMMENT
// this is a comment /* This is a multiline comment */
On docblocks vs. comments
T_COMMENT
T_DOC_COMMENT
// this is a comment /* This is a multiline comment */
/** ! * this is a docblock! */
On docblocks vs. comments
T_COMMENT
T_DOC_COMMENT
// this is a comment /* This is a multiline comment */
/** ! * this is a docblock! */
ignored����������� ������������������ by����������� ������������������ opcode����������� ������������������ cache
On docblocks vs. comments
T_COMMENT
T_DOC_COMMENT
// this is a comment /* This is a multiline comment */
/** ! * this is a docblock! */
ignored����������� ������������������ by����������� ������������������ opcode����������� ������������������ cache
cached����������� ������������������ by����������� ������������������ opcode����������� ������������������ cache
public class Customer!{! [Required]! [StringLength(50)]! public string Prename { get; set; }! ! [Column(TypeName = "image")]! public byte[] Image { get; set; }
@Entity! @Table(name = "people")! class Person implements Serializable {! @Id ! @GeneratedValue(strategy = GenerationType.AUTO) ! private Integer id;
class Reward !{ ! /** ! * @var integer $id ! * @deprecated! * @ORM\Column(name="id", type="integer") ! * @ORM\Id ! */ ! protected $id;
public class Customer!{! [Required]! [StringLength(50)]! public string Prename { get; set; }! ! [Column(TypeName = "image")]! public byte[] Image { get; set; }
@Entity! @Table(name = "people")! class Person implements Serializable {! @Id ! @GeneratedValue(strategy = GenerationType.AUTO) ! private Integer id;
class Reward !{ ! /** ! * @var integer $id ! * @deprecated! * @ORM\Column(name="id", type="integer") ! * @ORM\Id ! */ ! protected $id;
marker
public class Customer!{! [Required]! [StringLength(50)]! public string Prename { get; set; }! ! [Column(TypeName = "image")]! public byte[] Image { get; set; }
@Entity! @Table(name = "people")! class Person implements Serializable {! @Id ! @GeneratedValue(strategy = GenerationType.AUTO) ! private Integer id;
class Reward !{ ! /** ! * @var integer $id ! * @deprecated! * @ORM\Column(name="id", type="integer") ! * @ORM\Id ! */ ! protected $id;
marker
parameterized
Why?Why����������� ������������������ sho
uld����������� ������������������ I����������� ������������������ use����������� ������������������ ann
otations?
http://ecdesignrebels.blogspot.com
Are����������� ������������������ annotations����������� ������������������ for����������� ������������������ you?
I don’t know.
hate����������� ������������������ annotations
hate����������� ������������������ annotations
love����������� ������������������ annotations
hate����������� ������������������ annotations
love����������� ������������������ annotations
never����������� ������������������ used����������� ������������������ annotations
but����������� ������������������ its����������� ������������������ code,����������� ������������������ in����������� ������������������ comments!docblocks
harder
The downside or why not
but����������� ������������������ its����������� ������������������ code,����������� ������������������ in����������� ������������������ comments!docblocks
harder
The downside or why not
docblocks����������� ������������������ are����������� ������������������ first����������� ������������������ class����������� ������������������ citizens.
Its����������� ������������������ impossible����������� ������������������ to����������� ������������������ debug/test!
harder
The downside or why not
Its����������� ������������������ impossible����������� ������������������ to����������� ������������������ debug/test!
harder
The downside or why not
Test/debug����������� ������������������ annotation����������� ������������������ “executor”
The downside or why not
It����������� ������������������ does����������� ������������������ not����������� ������������������ perform!
The downside or why not
It����������� ������������������ does����������� ������������������ not����������� ������������������ perform!
Caching����������� ������������������ FTW!
Why I love Annotations
Easier����������� ������������������ to����������� ������������������ inject����������� ������������������ behavior����������� ������������������ without����������� ������������������ extending
Why I love Annotations
Easier����������� ������������������ to����������� ������������������ inject����������� ������������������ behavior����������� ������������������ without����������� ������������������ extendingDoctrine����������� ������������������ 1����������� ������������������ vs����������� ������������������ Doctrine����������� ������������������ 2
Why I love Annotations
Easier����������� ������������������ to����������� ������������������ inject����������� ������������������ behavior����������� ������������������ without����������� ������������������ extending
Contextualizes����������� ������������������ behavior/config����������� ������������������ in����������� ������������������ the����������� ������������������ object
Doctrine����������� ������������������ 1����������� ������������������ vs����������� ������������������ Doctrine����������� ������������������ 2
Why I love Annotations
Easier����������� ������������������ to����������� ������������������ inject����������� ������������������ behavior����������� ������������������ without����������� ������������������ extending
Contextualizes����������� ������������������ behavior/config����������� ������������������ in����������� ������������������ the����������� ������������������ object
Doctrine����������� ������������������ 1����������� ������������������ vs����������� ������������������ Doctrine����������� ������������������ 2
In����������� ������������������ object����������� ������������������ vs.����������� ������������������ external����������� ������������������ configuration����������� ������������������ file
Why I love Annotations
Easier����������� ������������������ to����������� ������������������ inject����������� ������������������ behavior����������� ������������������ without����������� ������������������ extending
Contextualizes����������� ������������������ behavior/config����������� ������������������ in����������� ������������������ the����������� ������������������ object
Doctrine����������� ������������������ 1����������� ������������������ vs����������� ������������������ Doctrine����������� ������������������ 2
In����������� ������������������ object����������� ������������������ vs.����������� ������������������ external����������� ������������������ configuration����������� ������������������ file
Its����������� ������������������ documented/stored����������� ������������������ by����������� ������������������ phpDocumentor
Why I love Annotations
Easier����������� ������������������ to����������� ������������������ inject����������� ������������������ behavior����������� ������������������ without����������� ������������������ extending
Contextualizes����������� ������������������ behavior/config����������� ������������������ in����������� ������������������ the����������� ������������������ object
Doctrine����������� ������������������ 1����������� ������������������ vs����������� ������������������ Doctrine����������� ������������������ 2
In����������� ������������������ object����������� ������������������ vs.����������� ������������������ external����������� ������������������ configuration����������� ������������������ file
Its����������� ������������������ documented/stored����������� ������������������ by����������� ������������������ phpDocumentorIts����������� ������������������ in����������� ������������������ docblocks,����������� ������������������ so����������� ������������������ its����������� ������������������ parsed
Why I love Annotations
<?php
class User!{!!!!!!!!protected $name!!!...!!!!!!!
}
<?php
class User!{!!!!!!!!protected $name!!!...!!!!!!!
}
-����������� ������������������ persist����������� ������������������ as����������� ������������������ varchar����������� ������������������
-����������� ������������������ length����������� ������������������ should����������� ������������������ not����������� ������������������ be����������� ������������������ ����������� ������������������
more����������� ������������������ then����������� ������������������ 255����������� ������������������
-����������� ������������������ should����������� ������������������ not����������� ������������������ be����������� ������������������ blank����������� ������������������
-����������� ������������������ only����������� ������������������ letters
<?php
class User!{!!!!!!!!protected $name!!!...!!!!!!!
}
-����������� ������������������ persist����������� ������������������ as����������� ������������������ varchar����������� ������������������
-����������� ������������������ length����������� ������������������ should����������� ������������������ not����������� ������������������ be����������� ������������������ ����������� ������������������
more����������� ������������������ then����������� ������������������ 255����������� ������������������
-����������� ������������������ should����������� ������������������ not����������� ������������������ be����������� ������������������ blank����������� ������������������
-����������� ������������������ only����������� ������������������ letters
MyProject\User:! properties:! name:! - NotBlank: ~! - MaxLength: 255
Validation
MyProject\User:! filters:! name:! - alpha
filter
MyProject\User:! type: entity! table: users! fields:! name:! type: string! length: 255
persistence
<?php
class User!{!!!!!!!!protected $name!!!...!!!!!!!
}
MyProject\User:! properties:! name:! - NotBlank: ~! - MaxLength: 255
Validation
MyProject\User:! filters:! name:! - alpha
filter
MyProject\User:! type: entity! table: users! fields:! name:! type: string! length: 255
persistence
/**! * @ORM\Column(‘string’, length=255)! * @Assert\NotBlank()! * @Assert\MaxLength(255)! * @Filter\Alpha()! */
<?php
class User!{!!!!!!!!protected $name!!!...!!!!!!!
}
/**! * @ORM\Column(‘string’, length=255)! * @Assert\NotBlank()! * @Assert\MaxLength(255)! * @Filter\Alpha()! */
Where?Where����������� ������������������ a
re����������� ������������������ annotatio
ns����������� ������������������ used?
http://ecdesignrebels.blogspot.com
Where?Where����������� ������������������ a
re����������� ������������������ annotatio
ns����������� ������������������ used?
http://ecdesignrebels.blogspot.com
class DataTest extends PHPUnit_Framework_TestCase !{ ! /** ! * @dataProvider provider ! * ! * @expectedException InvalidArgumentException ! * @expectedExceptionMessage Right Message ! */ ! public function testAdd($a, $b, $c) ! { ! /* Test code */ ! } ! ! public function provider() ! { ! return array( ! array(0, 0, 0), ! ); ! } !} !
expectations
repetition
/** ! * @ORM\Table("myentity") ! * @ORM\Entity(repositoryClass="MyEntityRepository") ! */ !class MyEntity !{ ! /** ! * @var integer $id ! * ! * @ORM\Column(name="id", type="integer") ! * @ORM\Id ! * @ORM\GeneratedValue(strategy="AUTO") ! */ ! protected $id; ! ! /** ! * @var string $title ! * ! * @ORM\Column(name="title", type="string", length=255) ! * @Assert\MaxLength(255) ! * @Assert\NotBlank() ! */ ! protected $title; ! ! /** ! * @var \Doctrine\Common\Collections\ArrayCollection $users ! * ! * @ORM\OneToMany(targetEntity="OtherEntity", mappedBy="myEntity", cascade={"persist","remove"}) ! */ ! protected $otherEntities; ! !}
persistance
association
/** ! * @Route("/myaction/{id}", name="myaction") ! * @Method("POST") ! * ! * @Template("MyBundle:MyController:my.html.twig") ! * ! * @param int $id ! * @return array ! */ !public function myAction($id) !{ ! ! /* Controller Logic */ ! ! return array('data' => $data); ! !} ! !!!class MyEntity !{ ! ! /** ! * @var string $title ! * ! * @ORM\Column(name="title", type="string", length=255) ! * @Assert\MaxLength(255) ! * @Assert\NotBlank() ! */ ! protected $title; ! !}!
routing
Validation
templating
/** ! * @FLOW3\Aspect ! */ !class LoggingAspect { ! ! /** ! * @FLOW3\Inject ! * @var \Examples\Forum\Logger\ApplicationLoggerInterface ! */ ! protected $applicationLogger; ! ! /** ! * Log a message if a post is deleted ! * ! * @param \TYPO3\FLOW3\AOP\JoinPointInterface $joinPoint ! * @FLOW3\Before("method(Examples\Forum\Domain\Model\Forum->deletePost())") ! * @return void ! */ ! public function logDeletePost(\TYPO3\FLOW3\AOP\JoinPointInterface $joinPoint) { ! $post = $joinPoint->getMethodArgument('post'); ! $this->applicationLogger->log('Removing post ' . $post->getTitle(), LOG_INFO); ! } ! !}!
Dependency����������� ������������������ Injection
AOP
How?How����������� ������������������ can����������� ������������������ i����������� ������������������
write����������� ������������������ my����������� ������������������ own����������� ������������������
annotations?
http://ecdesignrebels.blogspot.com
Annotations
My����������� ������������������ Project
Annotations
My����������� ������������������ ProjectAnnotation����������� ������������������ ����������� ������������������
Engine
/**! * @tag(parameters)! */!public function method()
Code
/**! * @tag(parameters)! */!public function method()
Code
ReflectionClass->getDocComment()
DOCBlock
/**! * @tag(parameters)! */
/**! * @tag(parameters)! */!public function method()
Code
ReflectionClass->getDocComment()
DOCBlock
/**! * @tag(parameters)! */
Tag() + parameters
Annotation����������� ������������������ Instances
/**! * @tag(parameters)! */!public function method()
Code
ReflectionClass->getDocComment()
Doctrine����������� ������������������ Annotations
phpDocumentor����������� ������������������ 2
Notoj
Annotation Engines
php-annotations
https://github.com/doctrine/annotations
https://github.com/phpDocumentor/phpDocumentor2
https://github.com/mindplay-dk/php-annotations
https://github.com/crodas/Notoj
Doctrine����������� ������������������ Annotations
phpDocumentor����������� ������������������ 2
Notoj
Annotation Engines
php-annotations
Doctrine����������� ������������������ Annotations
phpDocumentor����������� ������������������ 2
Notoj
Annotation Engines
php-annotations
1.1.2
2.0.2
1.1
0.16.1
Doctrine����������� ������������������ Annotations
phpDocumentor����������� ������������������ 2
Notoj
Annotation Engines
php-annotations
1.1.2
2.0.2
1.1
0.16.1
Doctrine����������� ������������������ Annotations
phpDocumentor����������� ������������������ 2
Notoj
Annotation Engines
php-annotations
1.1.2
2.0.2
1.1
0.16.1
doctrine/annotations
phpdocumentor/reflection-docblock
mindplay/annotations
crodas/notoj
Doctrine����������� ������������������ Annotations
phpDocumentor����������� ������������������ 2
Notoj
Annotation Engines
php-annotations
1.1.2
2.0.2
1.1
0.16.1
doctrine/annotations
phpdocumentor/reflection-docblock
mindplay/annotations
crodas/notoj
Doctrine����������� ������������������ Annotations
phpDocumentor����������� ������������������ 2
Notoj
Annotation Engines
php-annotations
1.1.2
2.0.2
1.1
0.16.1
full����������� ������������������ support
only����������� ������������������ string����������� ������������������
full����������� ������������������ support
full����������� ������������������ support
doctrine/annotations
phpdocumentor/reflection-docblock
mindplay/annotations
crodas/notoj
Doctrine����������� ������������������ Annotations
phpDocumentor����������� ������������������ 2
Notoj
Annotation Engines
php-annotations
1.1.2
2.0.2
1.1
0.16.1
full����������� ������������������ support
only����������� ������������������ string����������� ������������������
full����������� ������������������ support
full����������� ������������������ support
doctrine/annotations
phpdocumentor/reflection-docblock
mindplay/annotations
crodas/notoj
Doctrine����������� ������������������ Annotations
phpDocumentor����������� ������������������ 2
Notoj
Annotation Engines
php-annotations
1.1.2
2.0.2
1.1
0.16.1
full����������� ������������������ support
only����������� ������������������ string����������� ������������������
full����������� ������������������ support
full����������� ������������������ support
doctrine/annotations
phpdocumentor/reflection-docblock
mindplay/annotations
crodas/notoj
How����������� ������������������ it����������� ������������������ Works
<?php
/**! * @ORM\Column(‘string’)! * @Assert\NotBlank()! */
use Doctrine\ORM\Mapping as ORM;!use Symfony\Component\Validator\! Constraints as Assert;
How����������� ������������������ it����������� ������������������ Works
<?php
/**! * @ORM\Column(‘string’)! * @Assert\NotBlank()! */
use Doctrine\ORM\Mapping as ORM;!use Symfony\Component\Validator\! Constraints as Assert;
Declare����������� ������������������ which����������� ������������������ Annotations����������� ������������������ you����������� ������������������ will����������� ������������������ use
How����������� ������������������ it����������� ������������������ Works
AnnotationReader<?php
/**! * @ORM\Column(‘string’)! * @Assert\NotBlank()! */
use Doctrine\ORM\Mapping as ORM;!use Symfony\Component\Validator\! Constraints as Assert;
Declare����������� ������������������ which����������� ������������������ Annotations����������� ������������������ you����������� ������������������ will����������� ������������������ use
How����������� ������������������ it����������� ������������������ Works
AnnotationReader<?php
/**! * @ORM\Column(‘string’)! * @Assert\NotBlank()! */
new ORM\Column(‘string’)!new Assert\NotBlank()
“metadata”
use Doctrine\ORM\Mapping as ORM;!use Symfony\Component\Validator\! Constraints as Assert;
Declare����������� ������������������ which����������� ������������������ Annotations����������� ������������������ you����������� ������������������ will����������� ������������������ use
How����������� ������������������ it����������� ������������������ Works
AnnotationReader<?php
/**! * @ORM\Column(‘string’)! * @Assert\NotBlank()! */
new ORM\Column(‘string’)!new Assert\NotBlank()
Cache
“metadata”
Walker����������� ������������������ /����������� ������������������ code
use Doctrine\ORM\Mapping as ORM;!use Symfony\Component\Validator\! Constraints as Assert;
Declare����������� ������������������ which����������� ������������������ Annotations����������� ������������������ you����������� ������������������ will����������� ������������������ use
Input Filtering
DMS\Filter: https://github.com/rdohms/DMS
Input Filtering
DMS\Filter: https://github.com/rdohms/DMS
With����������� ������������������ Annotation����������� ������������������ Support!
Ingredients:
-����������� ������������������ Filter����������� ������������������ Rules-����������� ������������������ Filter����������� ������������������ Executioners����������� ������������������ -����������� ������������������ Filter����������� ������������������ Service����������� ������������������ -����������� ������������������ Annotation����������� ������������������ Engine����������� ������������������ -����������� ������������������ Annotated����������� ������������������ Objects
the����������� ������������������ annotation����������� ������������������ /����������� ������������������ metadata,����������� ������������������ configuration
applies����������� ������������������ the����������� ������������������ rules
the����������� ������������������ middle-man
gets����������� ������������������ the����������� ������������������ rules����������� ������������������ out����������� ������������������ of����������� ������������������ the����������� ������������������ docblocks
defines����������� ������������������ the����������� ������������������ rules
Filter����������� ������������������ Service
Filter����������� ������������������ EnforcerFiltered����������� ������������������ values
annotated����������� ������������������ object@Filter\StripTags(‘<b><i>’)
$executioner = new Filter\StripTags();!$executioner->filter($metadata, $value);
<p>Hello����������� ������������������ <b>World</b></p>
Hello����������� ������������������ <b>World</b>
“Configured”����������� ������������������ Rulesnew Rules\StripTags(‘<b><i>’);
Annotation����������� ������������������ Engine
The “rule”
<?php ! !namespace DMS\Filter\Rules; ! !/** ! * StripTags Rule ! * ! * @Annotation ! */ !class StripTags extends Rule !{ ! /** ! * String of allowed tags. Ex: <b><i><a> ! * ! * @var string ! */ ! public $allowed = null; ! ! /** ! * {@inheritDoc} ! */ ! public function getDefaultOption() ! { ! return 'allowed'; ! } !}
Usage:����������� ������������������ ����������� ������������������ use DMS\Filter\Rules as Filter;!!@Filter\StripTags(‘<b><i>’)
<?php ! !namespace DMS\Filter\Rules; ! !/** ! * StripTags Rule ! * ! * @Annotation ! */ !class StripTags extends Rule !{ ! /** ! * String of allowed tags. Ex: <b><i><a> ! * ! * @var string ! */ ! public $allowed = null; ! ! /** ! * {@inheritDoc} ! */ ! public function getDefaultOption() ! { ! return 'allowed'; ! } !}
tell����������� ������������������ doctrine����������� ������������������ this����������� ������������������ ����������� ������������������ is����������� ������������������ an����������� ������������������ annotation
Usage:����������� ������������������ ����������� ������������������ use DMS\Filter\Rules as Filter;!!@Filter\StripTags(‘<b><i>’)
<?php ! !namespace DMS\Filter\Rules; ! !/** ! * StripTags Rule ! * ! * @Annotation ! */ !class StripTags extends Rule !{ ! /** ! * String of allowed tags. Ex: <b><i><a> ! * ! * @var string ! */ ! public $allowed = null; ! ! /** ! * {@inheritDoc} ! */ ! public function getDefaultOption() ! { ! return 'allowed'; ! } !}
tell����������� ������������������ doctrine����������� ������������������ this����������� ������������������ ����������� ������������������ is����������� ������������������ an����������� ������������������ annotation
Usage:����������� ������������������ ����������� ������������������ use DMS\Filter\Rules as Filter;!!@Filter\StripTags(‘<b><i>’)
DMS\Filter\Rules\Rule: !public function __construct($options = null)
/**! * @My\Annotation(“name”, nullable=true)! */
/**! * @My\Annotation(“name”, nullable=true)! */
defaultProperty
/**! * @My\Annotation(“name”, nullable=true)! */
new My\Annotation($options);
defaultProperty
/**! * @My\Annotation(“name”, nullable=true)! */
new My\Annotation($options);
array:����������� ������������������ key����������� ������������������ =>����������� ������������������ value����������� ������������������ or����������� ������������������
string:����������� ������������������ value
defaultProperty
/**! * @My\Annotation(“name”, nullable=true)! */
new My\Annotation($options);
array:����������� ������������������ key����������� ������������������ =>����������� ������������������ value����������� ������������������ or����������� ������������������
string:����������� ������������������ value
defaultProperty
or
/**! * @My\Annotation(“name”, nullable=true)! */
new My\Annotation($options);
$a = new My\Annotation();!$a->nullable = true;!$a->{$a->getDefaultProperty()} = “name”;
array:����������� ������������������ key����������� ������������������ =>����������� ������������������ value����������� ������������������ or����������� ������������������
string:����������� ������������������ value
defaultProperty
or
The “enforcer”
<?php ! !namespace DMS\Filter\Filters; ! !use DMS\Filter\Rules\Rule; ! !/** ! * StripTags Rule ! * ! * @package DMS ! * @subpackage Filter ! * ! * @Annotation ! */ !class StripTags extends BaseFilter !{ ! ! /** ! * {@inheritDoc} ! * ! * @param \DMS\Filter\Rules\StripTags $filter ! * @param mixed $filter ! */ ! public function apply( Rule $filter, $value) ! { ! return strip_tags($value, $filter->allowed); ! } !} !
<?php ! !namespace DMS\Filter\Filters; ! !use DMS\Filter\Rules\Rule; ! !/** ! * StripTags Rule ! * ! * @package DMS ! * @subpackage Filter ! * ! * @Annotation ! */ !class StripTags extends BaseFilter !{ ! ! /** ! * {@inheritDoc} ! * ! * @param \DMS\Filter\Rules\StripTags $filter ! * @param mixed $filter ! */ ! public function apply( Rule $filter, $value) ! { ! return strip_tags($value, $filter->allowed); ! } !} !
Does����������� ������������������ the����������� ������������������ filtering
<?php ! !namespace DMS\Filter\Filters; ! !use DMS\Filter\Rules\Rule; ! !/** ! * StripTags Rule ! * ! * @package DMS ! * @subpackage Filter ! * ! * @Annotation ! */ !class StripTags extends BaseFilter !{ ! ! /** ! * {@inheritDoc} ! * ! * @param \DMS\Filter\Rules\StripTags $filter ! * @param mixed $filter ! */ ! public function apply( Rule $filter, $value) ! { ! return strip_tags($value, $filter->allowed); ! } !} !
Does����������� ������������������ the����������� ������������������ filtering
Rule����������� ������������������ has����������� ������������������ the����������� ������������������ configuration.Ex:����������� ������������������ allowed����������� ������������������ tags
The Filter Service
The����������� ������������������ Life����������� ������������������ of����������� ������������������ a����������� ������������������ Filter����������� ������������������ Service
The����������� ������������������ Life����������� ������������������ of����������� ������������������ a����������� ������������������ Filter����������� ������������������ Service
09:00 - DIC wake-up call new FilterService($reader);
The����������� ������������������ Life����������� ������������������ of����������� ������������������ a����������� ������������������ Filter����������� ������������������ Service
09:00 - DIC wake-up call
09:05 - Reply to emergency filter call
new FilterService($reader);
$service->filter($object);
The����������� ������������������ Life����������� ������������������ of����������� ������������������ a����������� ������������������ Filter����������� ������������������ Service
09:00 - DIC wake-up call
09:05 - Reply to emergency filter call
09:06 - Get Annotations for properties
new FilterService($reader);
$service->filter($object);
$reader->getPropertyAnnotations($p); $a = array(StripTags(), Alpha());
The����������� ������������������ Life����������� ������������������ of����������� ������������������ a����������� ������������������ Filter����������� ������������������ Service
09:00 - DIC wake-up call
09:05 - Reply to emergency filter call
09:06 - Get Annotations for properties
09:07 - Track down the Filters
new FilterService($reader);
$service->filter($object);
$reader->getPropertyAnnotations($p); $a = array(StripTags(), Alpha());
new Filters\StripTags();
The����������� ������������������ Life����������� ������������������ of����������� ������������������ a����������� ������������������ Filter����������� ������������������ Service
09:00 - DIC wake-up call
09:05 - Reply to emergency filter call
09:06 - Get Annotations for properties
09:07 - Track down the Filters
09:08 - Get values filtered
new FilterService($reader);
$service->filter($object);
$reader->getPropertyAnnotations($p); $a = array(StripTags(), Alpha());
new Filters\StripTags();
$filter->apply($rule, $value);
The����������� ������������������ Life����������� ������������������ of����������� ������������������ a����������� ������������������ Filter����������� ������������������ Service
09:00 - DIC wake-up call
09:05 - Reply to emergency filter call
09:06 - Get Annotations for properties
09:07 - Track down the Filters
09:08 - Get values filtered
09:10 - Update the object with new data
new FilterService($reader);
$service->filter($object);
$reader->getPropertyAnnotations($p); $a = array(StripTags(), Alpha());
new Filters\StripTags();
$filter->apply($rule, $value);
$object->prop = $newValue;
The����������� ������������������ Life����������� ������������������ of����������� ������������������ a����������� ������������������ Filter����������� ������������������ Service
09:00 - DIC wake-up call
09:05 - Reply to emergency filter call
09:06 - Get Annotations for properties
09:07 - Track down the Filters
09:08 - Get values filtered
09:10 - Update the object with new data
09:11 - send the object on its way
new FilterService($reader);
$service->filter($object);
$reader->getPropertyAnnotations($p); $a = array(StripTags(), Alpha());
new Filters\StripTags();
$filter->apply($rule, $value);
$object->prop = $newValue;
return $object;
The����������� ������������������ Life����������� ������������������ of����������� ������������������ a����������� ������������������ Filter����������� ������������������ Service
09:00 - DIC wake-up call
09:05 - Reply to emergency filter call
09:06 - Get Annotations for properties
09:07 - Track down the Filters
09:08 - Get values filtered
09:10 - Update the object with new data
09:11 - send the object on its way
new FilterService($reader);
$service->filter($object);
$reader->getPropertyAnnotations($p); $a = array(StripTags(), Alpha());
new Filters\StripTags();
$filter->apply($rule, $value);
$object->prop = $newValue;
return $object;
09:12 - DO IT ALL AGAIN!
The����������� ������������������ Life����������� ������������������ of����������� ������������������ a����������� ������������������ Filter����������� ������������������ Service
09:00 - DIC wake-up call
09:05 - Reply to emergency filter call
09:06 - Get Annotations for properties
09:07 - Track down the Filters
09:08 - Get values filtered
09:10 - Update the object with new data
09:11 - send the object on its way
new FilterService($reader);
$service->filter($object);
$reader->getPropertyAnnotations($p); $a = array(StripTags(), Alpha());
new Filters\StripTags();
$filter->apply($rule, $value);
$object->prop = $newValue;
return $object;
09:12 - DO IT ALL AGAIN!
//Iterate over all annotations !foreach($this->reader->getPropertyAnnotations($property) as $rule) { ! ! //Skip is its not a rule ! if ( ! $rule instanceof Rules\Rule ) continue; ! ! //Add Rule ! $metadata->addPropertyRule($property->getName(), $rule); ! !}
//Iterate over all annotations !foreach($this->reader->getPropertyAnnotations($property) as $rule) { ! ! //Skip is its not a rule ! if ( ! $rule instanceof Rules\Rule ) continue; ! ! //Add Rule ! $metadata->addPropertyRule($property->getName(), $rule); ! !}
get����������� ������������������ all����������� ������������������ annotation����������� ������������������ objects
//Iterate over all annotations !foreach($this->reader->getPropertyAnnotations($property) as $rule) { ! ! //Skip is its not a rule ! if ( ! $rule instanceof Rules\Rule ) continue; ! ! //Add Rule ! $metadata->addPropertyRule($property->getName(), $rule); ! !}
get����������� ������������������ all����������� ������������������ annotation����������� ������������������ objects
filter����������� ������������������ out����������� ������������������ “our”����������� ������������������ annotations
//Iterate over all annotations !foreach($this->reader->getPropertyAnnotations($property) as $rule) { ! ! //Skip is its not a rule ! if ( ! $rule instanceof Rules\Rule ) continue; ! ! //Add Rule ! $metadata->addPropertyRule($property->getName(), $rule); ! !}
glorified����������� ������������������ array
get����������� ������������������ all����������� ������������������ annotation����������� ������������������ objects
filter����������� ������������������ out����������� ������������������ “our”����������� ������������������ annotations
Necessary Object Calisthenics Disclaimer
FilterService
MetadataFactory ObjectWalker
Loader Cache
Reader ReflectionPropertyCache
//Get Doctrine Reader ! $reader = new Annotations\AnnotationReader(); ! $reader->setEnableParsePhpImports(true); ! ! //Load AnnotationLoader ! $loader = new Mapping\Loader\AnnotationLoader($reader); ! $this->loader = $loader; ! ! //Get a MetadataFactory ! $metadataFactory = new Mapping\ClassMetadataFactory($loader); ! ! //Get a Filter ! $filter = new DMS\Filter\Filter($metadataFactory); ! ! //Get your Entity ! $user = new App\Entity\User(); ! $user->name = "My <b>name</b>"; ! $user->email = " [email protected]"; ! ! //Filter you entity ! $filter->filter($user); ! ! echo $user->name; //"My name" ! echo $user->email; //"[email protected]" !
//Get Doctrine Reader ! $reader = new Annotations\AnnotationReader(); ! $reader->setEnableParsePhpImports(true); ! ! //Load AnnotationLoader ! $loader = new Mapping\Loader\AnnotationLoader($reader); ! $this->loader = $loader; ! ! //Get a MetadataFactory ! $metadataFactory = new Mapping\ClassMetadataFactory($loader); ! ! //Get a Filter ! $filter = new DMS\Filter\Filter($metadataFactory); ! ! //Get your Entity ! $user = new App\Entity\User(); ! $user->name = "My <b>name</b>"; ! $user->email = " [email protected]"; ! ! //Filter you entity ! $filter->filter($user); ! ! echo $user->name; //"My name" ! echo $user->email; //"[email protected]" !
put����������� ������������������ this����������� ������������������ in����������� ������������������ your����������� ������������������ DIC
//Get Doctrine Reader ! $reader = new Annotations\AnnotationReader(); ! $reader->setEnableParsePhpImports(true); ! ! //Load AnnotationLoader ! $loader = new Mapping\Loader\AnnotationLoader($reader); ! $this->loader = $loader; ! ! //Get a MetadataFactory ! $metadataFactory = new Mapping\ClassMetadataFactory($loader); ! ! //Get a Filter ! $filter = new DMS\Filter\Filter($metadataFactory); ! ! //Get your Entity ! $user = new App\Entity\User(); ! $user->name = "My <b>name</b>"; ! $user->email = " [email protected]"; ! ! //Filter you entity ! $filter->filter($user); ! ! echo $user->name; //"My name" ! echo $user->email; //"[email protected]" !
Calling����������� ������������������ the����������� ������������������ Service
put����������� ������������������ this����������� ������������������ in����������� ������������������ your����������� ������������������ DIC
What? Why? Where?
How?
http://plugins.jetbrains.com/plugin/7320?pr=phpStorm
PHP Annotations Pluginby Daniel Espendiller
Questions?
on����������� ������������������ twitterthese����������� ������������������ slides����������� ������������������ ����������� ������������������ will����������� ������������������ be����������� ������������������ here
http://slides.doh.ms
http://doh.ms
@rdohms