• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
 PHP Annotations: They exist! - JetBrains Webinar
 

PHP Annotations: They exist! - JetBrains Webinar

on

  • 33,881 views

Annotations are more than PHPDoc comments, they’re a fully-featured way of including additional information alongside your code. We might have rejected an RFC to add support into the PHP core, but ...

Annotations are more than PHPDoc comments, they’re a fully-featured way of including additional information alongside your code. We might have rejected an RFC to add support into the PHP core, but the community has embraced this tool anyway!

This session shows you who is doing what with annotations, and will give you some ideas on how to use the existing tools in your own projects to keep life simple. Developers, architects and anyone responsible for the technical direction of an application should attend this session.

Statistics

Views

Total Views
33,881
Views on SlideShare
33,839
Embed Views
42

Actions

Likes
17
Downloads
18
Comments
1

1 Embed 42

http://blog.jetbrains.com 42

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel

11 of 1 previous next

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
  • Next time you do this presentation, you need to update the 'FLOW3' logo on slides 74, 78, 94, 95. FLOW3 was renamed to 'Flow': http://flow.typo3.org/about/logos
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

     PHP Annotations: They exist! - JetBrains Webinar PHP Annotations: They exist! - JetBrains Webinar Presentation Transcript

    • Rafael
    •   Dohms Annotations
    •   in
    •   PHP @rdohms on
    •   twitter They
    •   Exist!
    • photocredit:EliWhite 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
    •   DMSFilter
    • what? What
    •   are
    •   annotations? 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.1
 Reflection
    •   supports
    •   
 getDocComments() ~2000 2005
    • First
    •    Annotation
    •    
    •   Engines
    •   in
    •   PHP phpDoc PHP
    •   5.1
 Reflection
    •   supports
    •   
 getDocComments() ~2000 2005
    • First
    •    Annotation
    •    
    •   Engines
    •   in
    •   PHP phpDoc PHP
    •   5.1
 Reflection
    •   supports
    •   
 getDocComments() ~2000 2005 2008
    • First
    •    Annotation
    •    
    •   Engines
    •   in
    •   PHP phpDoc PHP
    •   5.1
 Reflection
    •   supports
    •   
 getDocComments() ~2000 2005 2008 Doctrine
    •   2
    •   
 Annotation
    •   Engine
    • First
    •    Annotation
    •    
    •   Engines
    •   in
    •   PHP phpDoc PHP
    •   5.1
 Reflection
    •   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.1
 Reflection
    •   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.1
 Reflection
    •   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.1
 Reflection
    •   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.1
 Reflection
    •   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 /** ! * EntityReward ! * ! * @ORMTable("reward") ! * @ORMEntity(repositoryClass="RewardRepository") ! */ ! class Reward ! { ! /** ! * @var integer $id ! * ! * @ORMColumn(name="id", type="integer") ! * @ORMId ! * @ORMGeneratedValue(strategy="AUTO") ! */ ! protected $id; ! ! /** ! * @var string $title ! * ! * @ORMColumn(name="title", type="string", length=150, nullable=true) ! * ! * @AssertMaxLength(150) ! */ ! protected $title;
    • annotations /** ! * EntityReward ! * ! * @ORMTable("reward") ! * @ORMEntity(repositoryClass="RewardRepository") ! */ ! class Reward ! { ! /** ! * @var integer $id ! * ! * @ORMColumn(name="id", type="integer") ! * @ORMId ! * @ORMGeneratedValue(strategy="AUTO") ! */ ! protected $id; ! ! /** ! * @var string $title ! * ! * @ORMColumn(name="title", type="string", length=150, nullable=true) ! * ! * @AssertMaxLength(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! * @ORMColumn(name="id", type="integer") ! * @ORMId ! */ ! 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! * @ORMColumn(name="id", type="integer") ! * @ORMId ! */ ! 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! * @ORMColumn(name="id", type="integer") ! * @ORMId ! */ ! protected $id; marker parameterized
    • Why? Why
    •   should
    •   I
    •   use
    •   annotations? 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
    •   extending 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 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
    •   phpDocumentor Its
    •   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 MyProjectUser:! properties:! name:! - NotBlank: ~! - MaxLength: 255 Validation MyProjectUser:! filters:! name:! - alpha filter MyProjectUser:! type: entity! table: users! fields:! name:! type: string! length: 255 persistence
    • <?php class User! {! ! ! ! ! ! ! ! protected $name! ! ! ...! ! ! ! ! ! ! } MyProjectUser:! properties:! name:! - NotBlank: ~! - MaxLength: 255 Validation MyProjectUser:! filters:! name:! - alpha filter MyProjectUser:! type: entity! table: users! fields:! name:! type: string! length: 255 persistence /**! * @ORMColumn(‘string’, length=255)! * @AssertNotBlank()! * @AssertMaxLength(255)! * @FilterAlpha()! */
    • <?php class User! {! ! ! ! ! ! ! ! protected $name! ! ! ...! ! ! ! ! ! ! } /**! * @ORMColumn(‘string’, length=255)! * @AssertNotBlank()! * @AssertMaxLength(255)! * @FilterAlpha()! */
    • Where? Where
    •   are
    •   annotations
    •   used? http://ecdesignrebels.blogspot.com
    • Where? Where
    •   are
    •   annotations
    •   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
    • /** ! * @ORMTable("myentity") ! * @ORMEntity(repositoryClass="MyEntityRepository") ! */ ! class MyEntity ! { ! /** ! * @var integer $id ! * ! * @ORMColumn(name="id", type="integer") ! * @ORMId ! * @ORMGeneratedValue(strategy="AUTO") ! */ ! protected $id; ! ! /** ! * @var string $title ! * ! * @ORMColumn(name="title", type="string", length=255) ! * @AssertMaxLength(255) ! * @AssertNotBlank() ! */ ! protected $title; ! ! /** ! * @var DoctrineCommonCollectionsArrayCollection $users ! * ! * @ORMOneToMany(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 ! * ! * @ORMColumn(name="title", type="string", length=255) ! * @AssertMaxLength(255) ! * @AssertNotBlank() ! */ ! protected $title; ! ! }! routing Validation templating
    • /** ! * @FLOW3Aspect ! */ ! class LoggingAspect { ! ! /** ! * @FLOW3Inject ! * @var ExamplesForumLoggerApplicationLoggerInterface ! */ ! protected $applicationLogger; ! ! /** ! * Log a message if a post is deleted ! * ! * @param TYPO3FLOW3AOPJoinPointInterface $joinPoint ! * @FLOW3Before("method(ExamplesForumDomainModelForum->deletePost())") ! * @return void ! */ ! public function logDeletePost(TYPO3FLOW3AOPJoinPointInterface $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
    •   Project Annotation
    •   
    •    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 /**! * @ORMColumn(‘string’)! * @AssertNotBlank()! */ use DoctrineORMMapping as ORM;! use SymfonyComponentValidator! Constraints as Assert;
    • How
    •   it
    •   Works <?php /**! * @ORMColumn(‘string’)! * @AssertNotBlank()! */ use DoctrineORMMapping as ORM;! use SymfonyComponentValidator! Constraints as Assert; Declare
    •   which
    •   Annotations
    •    you
    •   will
    •   use
    • How
    •   it
    •   Works AnnotationReader <?php /**! * @ORMColumn(‘string’)! * @AssertNotBlank()! */ use DoctrineORMMapping as ORM;! use SymfonyComponentValidator! Constraints as Assert; Declare
    •   which
    •   Annotations
    •    you
    •   will
    •   use
    • How
    •   it
    •   Works AnnotationReader <?php /**! * @ORMColumn(‘string’)! * @AssertNotBlank()! */ new ORMColumn(‘string’)! new AssertNotBlank() “metadata” use DoctrineORMMapping as ORM;! use SymfonyComponentValidator! Constraints as Assert; Declare
    •   which
    •   Annotations
    •    you
    •   will
    •   use
    • How
    •   it
    •   Works AnnotationReader <?php /**! * @ORMColumn(‘string’)! * @AssertNotBlank()! */ new ORMColumn(‘string’)! new AssertNotBlank() Cache “metadata” Walker
    •   /
    •   code use DoctrineORMMapping as ORM;! use SymfonyComponentValidator! Constraints as Assert; Declare
    •   which
    •   Annotations
    •    you
    •   will
    •   use
    • Input Filtering DMSFilter: https://github.com/rdohms/DMS
    • Input Filtering DMSFilter: 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 @FilterStripTags(‘<b><i>’) $executioner = new FilterStripTags();! $executioner->filter($metadata, $value); <p>Hello
    •   <b>World</b></p> Hello
    •   <b>World</b> “Configured”
    •   Rules new RulesStripTags(‘<b><i>’); Annotation
    •   Engine
    • The “rule”
    • <?php ! ! namespace DMSFilterRules; ! ! /** ! * 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 DMSFilterRules as Filter;! ! @FilterStripTags(‘<b><i>’)
    • <?php ! ! namespace DMSFilterRules; ! ! /** ! * 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 DMSFilterRules as Filter;! ! @FilterStripTags(‘<b><i>’)
    • <?php ! ! namespace DMSFilterRules; ! ! /** ! * 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 DMSFilterRules as Filter;! ! @FilterStripTags(‘<b><i>’) DMSFilterRulesRule:
 ! public function __construct($options = null)
    • /**! * @MyAnnotation(“name”, nullable=true)! */
    • /**! * @MyAnnotation(“name”, nullable=true)! */ defaultProperty
    • /**! * @MyAnnotation(“name”, nullable=true)! */ new MyAnnotation($options); defaultProperty
    • /**! * @MyAnnotation(“name”, nullable=true)! */ new MyAnnotation($options); array:
    •   key
    •   =>
    •   value
    •    or
    •    string:
    •   value defaultProperty
    • /**! * @MyAnnotation(“name”, nullable=true)! */ new MyAnnotation($options); array:
    •   key
    •   =>
    •   value
    •    or
    •    string:
    •   value defaultProperty or
    • /**! * @MyAnnotation(“name”, nullable=true)! */ new MyAnnotation($options); $a = new MyAnnotation();! $a->nullable = true;! $a->{$a->getDefaultProperty()} = “name”; array:
    •   key
    •   =>
    •   value
    •    or
    •    string:
    •   value defaultProperty or
    • The “enforcer”
    • <?php ! ! namespace DMSFilterFilters; ! ! use DMSFilterRulesRule; ! ! /** ! * StripTags Rule ! * ! * @package DMS ! * @subpackage Filter ! * ! * @Annotation ! */ ! class StripTags extends BaseFilter ! { ! ! /** ! * {@inheritDoc} ! * ! * @param DMSFilterRulesStripTags $filter ! * @param mixed $filter ! */ ! public function apply( Rule $filter, $value) ! { ! return strip_tags($value, $filter->allowed); ! } ! } !
    • <?php ! ! namespace DMSFilterFilters; ! ! use DMSFilterRulesRule; ! ! /** ! * StripTags Rule ! * ! * @package DMS ! * @subpackage Filter ! * ! * @Annotation ! */ ! class StripTags extends BaseFilter ! { ! ! /** ! * {@inheritDoc} ! * ! * @param DMSFilterRulesStripTags $filter ! * @param mixed $filter ! */ ! public function apply( Rule $filter, $value) ! { ! return strip_tags($value, $filter->allowed); ! } ! } ! Does
    •   the
    •   filtering
    • <?php ! ! namespace DMSFilterFilters; ! ! use DMSFilterRulesRule; ! ! /** ! * StripTags Rule ! * ! * @package DMS ! * @subpackage Filter ! * ! * @Annotation ! */ ! class StripTags extends BaseFilter ! { ! ! /** ! * {@inheritDoc} ! * ! * @param DMSFilterRulesStripTags $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 FiltersStripTags();
    • 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 FiltersStripTags(); $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 FiltersStripTags(); $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 FiltersStripTags(); $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 FiltersStripTags(); $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 FiltersStripTags(); $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 RulesRule ) 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 RulesRule ) 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 RulesRule ) 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 RulesRule ) 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 AnnotationsAnnotationReader(); ! $reader->setEnableParsePhpImports(true); ! ! //Load AnnotationLoader ! $loader = new MappingLoaderAnnotationLoader($reader); ! $this->loader = $loader; ! ! //Get a MetadataFactory ! $metadataFactory = new MappingClassMetadataFactory($loader); ! ! //Get a Filter ! $filter = new DMSFilterFilter($metadataFactory); ! ! //Get your Entity ! $user = new AppEntityUser(); ! $user->name = "My <b>name</b>"; ! $user->email = " email@mail.com"; ! ! //Filter you entity ! $filter->filter($user); ! ! echo $user->name; //"My name" ! echo $user->email; //"email@mail.com" !
    • //Get Doctrine Reader ! $reader = new AnnotationsAnnotationReader(); ! $reader->setEnableParsePhpImports(true); ! ! //Load AnnotationLoader ! $loader = new MappingLoaderAnnotationLoader($reader); ! $this->loader = $loader; ! ! //Get a MetadataFactory ! $metadataFactory = new MappingClassMetadataFactory($loader); ! ! //Get a Filter ! $filter = new DMSFilterFilter($metadataFactory); ! ! //Get your Entity ! $user = new AppEntityUser(); ! $user->name = "My <b>name</b>"; ! $user->email = " email@mail.com"; ! ! //Filter you entity ! $filter->filter($user); ! ! echo $user->name; //"My name" ! echo $user->email; //"email@mail.com" ! put
    •   this
    •   in
    •   your
    •   DIC
    • //Get Doctrine Reader ! $reader = new AnnotationsAnnotationReader(); ! $reader->setEnableParsePhpImports(true); ! ! //Load AnnotationLoader ! $loader = new MappingLoaderAnnotationLoader($reader); ! $this->loader = $loader; ! ! //Get a MetadataFactory ! $metadataFactory = new MappingClassMetadataFactory($loader); ! ! //Get a Filter ! $filter = new DMSFilterFilter($metadataFactory); ! ! //Get your Entity ! $user = new AppEntityUser(); ! $user->name = "My <b>name</b>"; ! $user->email = " email@mail.com"; ! ! //Filter you entity ! $filter->filter($user); ! ! echo $user->name; //"My name" ! echo $user->email; //"email@mail.com" ! Calling
    •   the
    •   Service put
    •   this
    •   in
    •   your
    •   DIC
    • What? Why? Where? How?
    • http://plugins.jetbrains.com/plugin/7320?pr=phpStorm PHP Annotations Plugin by Daniel Espendiller
    • Questions? on
    •   twitter these
    •   slides
    •   
    •    will
    •   be
    •   here http://slides.doh.ms http://doh.ms @rdohms