Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Annotating with Annotations

13,815 views

Published on

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.

Published in: Technology
  • Be the first to comment

Annotating with Annotations

  1. *
  2.  TrueNorthPHP
  3.  -
  4.  Toronto/2012 Annotating
  5.  with
  6.   Annotations A
  7.  look
  8.  into
  9.  Annotations
  10.  in
  11.  PHP on
  12.  twitter Rafael
  13.  Dohms @rdohms
  14. *
  15.  TrueNorthPHP
  16.  -
  17.  Toronto/2012 Annotating
  18.  with
  19.   Annotations A
  20.  look
  21.  into
  22.  Annotations
  23.  in
  24.  PHP on
  25.  twitter Rafael
  26.  Dohms @rdohms
  27. Rafael Dohms photo credit: Eli White @rdohms Evangelist, Speaker and Contributor.Developer at WEBclusive.Enabler at AmsterdamPHP.
  28. a
  29.  little
  30.  history existing
  31.  uses What? Why? Where? How? ustom
  32.  ann otations Impl ementing
  33.  c DMSFilter based
  34.  on
  35.   show
  36.  me
  37.  the
  38.  code!
  39. http://ecdesignrebels.blogspot.com w h a t? ta tio ns? re
  40.  an noW ha t
  41.  a
  42. -- In English --An annotation is a note that is made while reading any form of text.
  43. something
  44.  that
  45.  describes
  46.  an
  47.  aspect
  48.  of
  49.  the
  50.  subject -- In English --An annotation is a note that is made while reading any form of text.
  51. -- In Code Speak --“An annotation describes behavior of code and affects your application in runtime.” “Annotations do not directly affect program semantics”
  52. -- In Code Speak --“An annotation describes behavior of code and affects your application in runtime.” “Annotations do not directly affect program semantics” just
  53.  like
  54.  your
  55.  notes
  56. In
  57.  2004:
  58.  Metadata
  59.  or
  60.  “General
  61.  purpose
  62.  Annotations”
  63. In
  64.  2004:
  65.  Metadata
  66.  or
  67.  “General
  68.  purpose
  69.  Annotations” available
  70.  at
  71.  Runtime
  72.  using
  73.  Reflection
  74. In
  75.  2004:
  76.  Metadata
  77.  or
  78.  “General
  79.  purpose
  80.  Annotations” @Entity @Table(name = people) class Person implements Serializable { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Integer id; @Column(length = 32) private String name; available
  81.  at
  82.  Runtime
  83.  using
  84.  Reflection
  85. In
  86.  2004:
  87.  Metadata
  88.  or
  89.  “General
  90.  purpose
  91.  Annotations” specific
  92.  syntax @Entity @Table(name = people) class Person implements Serializable { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Integer id; @Column(length = 32) private String name; available
  93.  at
  94.  Runtime
  95.  using
  96.  Reflection
  97. No
  98.  core
  99.  annotation
  100.  support
  101. Questions?
  102. Questions?I’m
  103.  kidding!
  104. phpDoc~2000
  105. PHP
  106.  5.1 Reflection
  107.  supports
  108.   getDocComments()phpDoc~2000 2005
  109. PHP
  110.  5.1 Reflection
  111.  supports
  112.   getDocComments()phpDoc~2000 2005 First
  113.   Annotation
  114.  Engines
  115.  in
  116.  PHP
  117. PHP
  118.  5.1 Reflection
  119.  supports
  120.   getDocComments()phpDoc~2000 2005 2008 First
  121.   Annotation
  122.  Engines
  123.  in
  124.  PHP
  125. PHP
  126.  5.1 Reflection
  127.  supports
  128.   getDocComments()phpDoc~2000 2005 2008 First
  129.   Doctrine
  130.  2
  131.   Annotation Annotation
  132.  Engine
  133.  Engines
  134.  in
  135.  PHP
  136. PHP
  137.  5.1 Reflection
  138.  supports
  139.   getDocComments() RFC:
  140.  Annotations
  141.   in
  142.  core
  143.  w/
  144.  custom
  145.  phpDoc syntax~2000 2005 2008 2010 First
  146.   Doctrine
  147.  2
  148.   Annotation Annotation
  149.  Engine
  150.  Engines
  151.  in
  152.  PHP
  153. PHP
  154.  5.1 Reflection
  155.  supports
  156.   getDocComments() RFC:
  157.  Annotations
  158.   ED CTustom
  159.   in
  160.  core
  161.  JE/
  162.  c wphpDoc E Rsyntax~2000 2005 2008 2010 First
  163.   Doctrine
  164.  2
  165.   Annotation Annotation
  166.  Engine
  167.  Engines
  168.  in
  169.  PHP
  170. PHP
  171.  5.1 RFC:
  172.  DocBlock
  173.   Reflection
  174.  supports
  175.   Annotations getDocComments() “in
  176.  discussion” RFC:
  177.  Annotations
  178.   ED CTustom
  179.   in
  180.  core
  181.  JE/
  182.  c wphpDoc E Rsyntax~2000 2005 2008 2010 2011 First
  183.   Doctrine
  184.  2
  185.   Annotation Annotation
  186.  Engine
  187.  Engines
  188.  in
  189.  PHP
  190. PHP
  191.  5.1 RFC:
  192.  DocBlock
  193.   Reflection
  194.  supports
  195.   Annotations getDocComments() “in
  196.  discussion” RFC:
  197.  Annotations
  198.   ED CTustom
  199.   in
  200.  core
  201.  JE/
  202.  c wphpDoc E Rsyntax~2000 2005 2008 2010 2011 ? First
  203.   Doctrine
  204.  2
  205.   Annotation Annotation
  206.  Engine
  207.  Engines
  208.  in
  209.  PHP
  210. PHP
  211.  5.1 RFC:
  212.  DocBlock
  213.   Reflection
  214.  supports
  215.   Annotations getDocComments() /** * CaasBundleFundingBundleEntityReward “in
  216.  discussion” * RFC:
  217.  Annotations
  218.   ED * @ORMTable(reward) CTustom
  219.   * @ORMEntity(repositoryClass=CaasBundleFundingBundleEntityRewardRepository) */ class Reward in
  220.  core
  221.  JE/
  222.  c w E {phpDoc /** Rsyntax ? * @var integer $id * * @ORMColumn(name=id, type=integer) * @ORMId * @ORMGeneratedValue(strategy=AUTO)~2000 */ protected $id; 2005 2008 2010 2011 /** * @var string $title * * @ORMColumn(name=title, type=string, length=150, nullable=true) * First
  223.   * @AssertMaxLength(150) */ protected $title; Doctrine
  224.  2
  225.   Annotation Annotation
  226.  Engine
  227.  Engines
  228.  in
  229.  PHP
  230. Note:
  231. Note://
  232.  This
  233.  is
  234.  a
  235.  comment T_COMMENT/*
  236.  This
  237.  is
  238.  a
  239.  multiline
  240.  comment
  241.  */
  242. Note://
  243.  This
  244.  is
  245.  a
  246.  comment T_COMMENT/*
  247.  This
  248.  is
  249.  a
  250.  multiline
  251.  comment
  252.  *//**
  253.  
  254.  *
  255.  This
  256.  is
  257.  a
  258.  doc
  259.  block T_DOC_COMMENT
  260.  */
  261. /** * @deprecated * * @ORMColumn(‘string’, length=255) */public function method()
  262. marker/** * @deprecated * * @ORMColumn(‘string’, length=255) */public function method()
  263. marker parameterized/** * @deprecated * * @ORMColumn(‘string’, length=255) */public function method()
  264. http://ecdesignrebels.blogspot.com Wh y ?
  265.  an no tatio ns? uld
  266.  I
  267.   use /co ns? hy
  268.   sho e
  269.  p rosW t
  270.   are
  271.  th w ha
  272. -
  273. Harder
  274.  to
  275.  debug
  276.  (dynamic
  277.  code)-
  278. Harder
  279.  to
  280.  debug
  281.  (dynamic
  282.  code)- Performance
  283.  hit
  284.  (non-native
  285.  code)
  286. Harder
  287.  to
  288.  debug
  289.  (dynamic
  290.  code)- Performance
  291.  hit
  292.  (non-native
  293.  code) Its
  294.  implemented
  295.  in
  296.  comments
  297.  docblocks!
  298. +
  299. Easier
  300.  to
  301.  inject
  302.  behavior
  303.  without
  304.  extending+
  305. Easier
  306.  to
  307.  inject
  308.  behavior
  309.  without
  310.  extending Doctrine
  311.  1
  312.  vs
  313.  Doctrine
  314.  2+
  315. Easier
  316.  to
  317.  inject
  318.  behavior
  319.  without
  320.  extending Doctrine
  321.  1
  322.  vs
  323.  Doctrine
  324.  2 Contextualizes
  325.  behavior/config
  326.  in
  327.  the
  328.  object+
  329. Easier
  330.  to
  331.  inject
  332.  behavior
  333.  without
  334.  extending Doctrine
  335.  1
  336.  vs
  337.  Doctrine
  338.  2 Contextualizes
  339.  behavior/config
  340.  in
  341.  the
  342.  object+ In
  343.  object
  344.  vs.
  345.  external
  346.  configuration
  347.  file
  348. Easier
  349.  to
  350.  inject
  351.  behavior
  352.  without
  353.  extending Doctrine
  354.  1
  355.  vs
  356.  Doctrine
  357.  2 Contextualizes
  358.  behavior/config
  359.  in
  360.  the
  361.  object+ In
  362.  object
  363.  vs.
  364.  external
  365.  configuration
  366.  file Its
  367.  documented/stored
  368.  by
  369.  phpDocumentor
  370. Easier
  371.  to
  372.  inject
  373.  behavior
  374.  without
  375.  extending Doctrine
  376.  1
  377.  vs
  378.  Doctrine
  379.  2 Contextualizes
  380.  behavior/config
  381.  in
  382.  the
  383.  object+ In
  384.  object
  385.  vs.
  386.  external
  387.  configuration
  388.  file Its
  389.  documented/stored
  390.  by
  391.  phpDocumentor Its
  392.  in
  393.  docblocks,
  394.  so
  395.  its
  396.  parsed
  397. ?phpclass User{ protected $name ...}
  398. ?php -
  399.  persist
  400.  as
  401.  varchar length
  402.  should
  403.  not
  404.  be
  405.  class User{ -
  406.   more
  407.  then
  408.  255 -
  409.  should
  410.  not
  411.  be
  412.  blank -
  413.  only
  414.  letters protected $name ...}
  415. persistence DoctrineTestsORMMappingUser: type: entity table: cms_users?php id: id: -
  416.  persist
  417.  as
  418.  varchar type: integer length
  419.  should
  420.  not
  421.  be
  422.  class User generator:{ -
  423.   strategy: AUTO more
  424.  then
  425.  255 fields: name: -
  426.  should
  427.  not
  428.  be
  429.  blank type: string -
  430.  only
  431.  letters length: 255 protected $name Validation AcmeBlogBundleEntityAuthor: properties: name: ... - NotBlank: ~ - MaxLength: 255 filter AcmeBlogBundleEntityAuthor:} filters: name: - alpha
  432. persistence Validation?phpclass User filter{ /** * @ORMColumn(‘string’, length=255) * @AssertNotBlank() * @AssertMaxLength(255) * @FilterAlpha() */ protected $name ...}
  433. ? http://ecdesignrebels.blogspot.comW h e r e tions
  434.  used?
  435.  ann ota er e
  436.   areWh
  437. class DataTest extends PHPUnit_Framework_TestCase{ /** * @dataProvider provider repetition * * @expectedException InvalidArgumentException * @expectedExceptionMessage Right Message */ public function testAdd($a, $b, $c) expectations { /* Test code */ } public function provider() { return array( array(0, 0, 0), ); }}
  438. /** * @ORMTable(myentity) * @ORMEntity(repositoryClass=MyEntityRepository) */class MyEntity{ /** * @var integer $id * * @ORMColumn(name=id, type=integer) * @ORMId * @ORMGeneratedValue(strategy=AUTO) persistance */ protected $id; /** * @var string $title * * @ORMColumn(name=title, type=string, length=255) association * @AssertMaxLength(255) * @AssertNotBlank() */ protected $title; /** * @var DoctrineCommonCollectionsArrayCollection $users * * @ORMOneToMany(targetEntity=OtherEntity, mappedBy=myEntity, cascade={persist,remove}) */ protected $otherEntities;}
  439. /** * @Route(/myaction/{id}, name=myaction) * @Method(POST) * * @Template(MyBundle:MyController:my.html.twig) * * @param int $id * @return array routing */public function myAction($id){ /* Controller Logic */ templating return array(data = $data);}class MyEntity{ /** * @var string $title * * @ORMColumn(name=title, type=string, length=255) * @AssertMaxLength(255) * @AssertNotBlank() */ protected $title;} Validation
  440. /** Dependency
  441.  Injection * @FLOW3Aspect */class LoggingAspect { /** * @FLOW3Inject * @var ExamplesForumLoggerApplicationLoggerInterface AOP */ 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); }}
  442. http://ecdesignrebels.blogspot.comH o w ? e
  443.   my
  444.  ow n
  445.   rit
  446.  i
  447.  w ns?How
  448.   can tio a nno ta
  449. My
  450.  ProjectAnnotations
  451. Annotation
  452.   Engine My
  453.  ProjectAnnotations
  454. /** * @tag parameters */public function method() Code
  455. /**ReflectionClass-getDocComment() * @tag parameters */ public function method() Code
  456. /** ReflectionClass-getDocComment() * @tag parameters */ public function method() Code/** * @tag parameters */DOCBlock
  457. /** ReflectionClass-getDocComment() * @tag parameters */ public function method() Code/** * @tag parameters */DOCBlock
  458. /** ReflectionClass-getDocComment() * @tag parameters */ public function method() Code/** * @tag parameters */DOCBlock Tag() + parameters Annotation
  459.  Instances
  460. Annotation Engines Doctrine
  461.  Commons ZF2
  462.  Annotations phpDocumentor
  463.  2 Notoj abandoned? addendum php-annotations Stubble
  464. Annotation Engines Notoj 2.3 2.0
  465.  -
  466.  alpha ?Parameterized marker parameterizedvery
  467.  mature maturing new
  468. Annotation Engines Notoj 2.3 2.0
  469.  -
  470.  alpha ?Parameterized marker parameterizedvery
  471.  mature maturing new
  472. How
  473.  it
  474.  Works ?php use DoctrineORMMapping as ORM; use SymfonyComponentValidator Constraints as Assert; /** * @ORMColumn(‘string’) * @AssertNotBlank() */
  475. How
  476.  it
  477.  Works Declare
  478.  which
  479.  Annotations
  480.   you
  481.  will
  482.  use ?php use DoctrineORMMapping as ORM; use SymfonyComponentValidator Constraints as Assert; /** * @ORMColumn(‘string’) * @AssertNotBlank() */
  483. How
  484.  it
  485.  Works Declare
  486.  which
  487.  Annotations
  488.   you
  489.  will
  490.  useAnnotationReader ?php use DoctrineORMMapping as ORM; use SymfonyComponentValidator Constraints as Assert; /** * @ORMColumn(‘string’) * @AssertNotBlank() */
  491. How
  492.  it
  493.  Works Declare
  494.  which
  495.  Annotations
  496.   you
  497.  will
  498.  useAnnotationReader ?php use DoctrineORMMapping as ORM; use SymfonyComponentValidator Constraints as Assert; /** * @ORMColumn(‘string’) * @AssertNotBlank() “metadata” */new ORMColumn(‘string’)new AssertNotBlank()
  499. How
  500.  it
  501.  Works Declare
  502.  which
  503.  Annotations
  504.   you
  505.  will
  506.  useAnnotationReader ?php use DoctrineORMMapping as ORM; use SymfonyComponentValidator Constraints as Assert; /** * @ORMColumn(‘string’) * @AssertNotBlank() “metadata” */new ORMColumn(‘string’)new AssertNotBlank() Walker
  507.  /
  508.  code Cache
  509. DMSFilterhttps://github.com/rdohms/DMS
  510. The
  511.  Gears
  512. The
  513.  Gears YourApp DoctrineCommons
  514. The
  515.  Gears Reader YourApp DoctrineCommons
  516. The
  517.  Gears Parsing Reader YourApp DoctrineCommons
  518. The
  519.  Gears Parsing Filter Reader YourApp DoctrineCommons
  520. The
  521.  Gears “Enforcing” Parsing Filter Reader YourApp DoctrineCommons
  522. The
  523.  Gears “Enforcing” Parsing Filter ReaderAnnotatedObject YourApp DoctrineCommons
  524. The
  525.  Gears “Enforcing” Parsing Filter ReaderAnnotatedObject MyAnnotation YourApp DoctrineCommons
  526. The
  527.  Gears “Enforcing” Parsing Filter ReaderAnnotatedObject filter() MyAnnotation YourApp DoctrineCommons
  528. The
  529.  Gears “Enforcing” Parsing Filter ReaderAnnotatedObject filter() getMethodAnnotation() MyAnnotation YourApp DoctrineCommons
  530. The
  531.  Gears “Enforcing” Parsing Filter ReaderAnnotatedObject filter() getMethodAnnotation() MyAnnotation YourApp DoctrineCommons
  532. The
  533.  Gears “Enforcing” Parsing Filter ReaderAnnotatedObject filter() getMethodAnnotation() filtered value MyAnnotation YourApp DoctrineCommons
  534. Usage:
  535.  @FilterNoDogs()namespace FilterRule;/** * @Annotation */class NoDogs{ public function __construct($options) { /* no options */ } public function filter($value) { return str_replace(dogs, , (string) $value); }}
  536. Usage:
  537.  @FilterNoDogs()namespace FilterRule;/** * @Annotation tell
  538.  doctrine
  539.  this
  540.   */class NoDogs is
  541.  an
  542.  annotation{ public function __construct($options) { /* no options */ } public function filter($value) { return str_replace(dogs, , (string) $value); }}
  543. Usage:
  544.  @FilterNoDogs()namespace FilterRule;/** * @Annotation tell
  545.  doctrine
  546.  this
  547.   */class NoDogs is
  548.  an
  549.  annotation{ public function __construct($options) { /* no options */ } array
  550.  of
  551.  the
  552.  parameters public function filter($value) { return str_replace(dogs, , (string) $value); }}
  553. Usage:
  554.  @FilterNoDogs()namespace FilterRule;/** * @Annotation tell
  555.  doctrine
  556.  this
  557.   */class NoDogs is
  558.  an
  559.  annotation{ public function __construct($options) { /* no options */ } array
  560.  of
  561.  the
  562.  parameters public function filter($value) { return str_replace(dogs, , (string) $value); }} this
  563.  is
  564.  the
  565.  effect
  566.  of
  567.   our
  568.  annotation
  569. namespace Filter;class Filter{ private $reader; public function __construct(DoctrineCommonAnnotationsReader $reader) { $this-reader = $reader; } public function filter($object) { $reflectionObject = new ReflectionObject($object); foreach ($reflectionObject-getProperties() as $reflectionProperty) { $this-filterProperty($object, $reflectionProperty); } } public function filterProperty($object, $reflectionProperty) { // fetch the @NoDog annotation from the annotation reader $annotation = $this-reader-getMethodAnnotation( $reflectionProperty, FilterRuleNoDog); if (null === $annotation) { return; } $reflectionProperty-setAccessible(true); $value = $reflectionProperty-getValue($object); $filteredValue = $annotation-filter($value); $reflectionProperty-setValue( $filteredValue ); }}
  570. namespace Filter;class Filter{ private $reader; public function __construct(DoctrineCommonAnnotationsReader $reader) { $this-reader = $reader; } public function filter($object) { $reflectionObject = new ReflectionObject($object); foreach ($reflectionObject-getProperties() as $reflectionProperty) { $this-filterProperty($object, $reflectionProperty); } } Get
  571.  only
  572.  our
  573.   annotation public function filterProperty($object, $reflectionProperty) { // fetch the @NoDog annotation from the annotation reader $annotation = $this-reader-getMethodAnnotation( $reflectionProperty, FilterRuleNoDog); if (null === $annotation) { return; } $reflectionProperty-setAccessible(true); $value = $reflectionProperty-getValue($object); $filteredValue = $annotation-filter($value); $reflectionProperty-setValue( $filteredValue ); }}
  574. namespace Filter;class Filter{ private $reader; public function __construct(DoctrineCommonAnnotationsReader $reader) { $this-reader = $reader; } public function filter($object) { $reflectionObject = new ReflectionObject($object); foreach ($reflectionObject-getProperties() as $reflectionProperty) { $this-filterProperty($object, $reflectionProperty); } } Get
  575.  only
  576.  our
  577.   annotation public function filterProperty($object, $reflectionProperty) { // fetch the @NoDog annotation from the annotation reader $annotation = $this-reader-getMethodAnnotation( $reflectionProperty, FilterRuleNoDog); if (null === $annotation) { return; } $reflectionProperty-setAccessible(true); $value = $reflectionProperty-getValue($object); Make
  578.  Annotation
  579.   $filteredValue = $annotation-filter($value); $reflectionProperty-setValue( $filteredValue );} } affect
  580.  application
  581. Taking
  582.  it
  583.  up
  584.  a
  585.  notch
  586. Taking
  587.  it
  588.  up
  589.  a
  590.  notch Filter Reader
  591. Taking
  592.  it
  593.  up
  594.  a
  595.  notch Filter Reader Walker Loader
  596. Taking
  597.  it
  598.  up
  599.  a
  600.  notch Filter Parsing Using/Walking Reader Walker Loading Loader
  601. Taking
  602.  it
  603.  up
  604.  a
  605.  notch Filter Parsing Using/Walking Reader Walker Loading Loader Filters
  606.  Annotations
  607. Taking
  608.  it
  609.  up
  610.  a
  611.  notch Filter Parsing Using/Walking Reader Walker Loading Loader navigates
  612.  object,
  613.   Filters
  614.  Annotations reflects
  615.  and
  616.  filters
  617. Taking
  618.  it
  619.  up
  620.  a
  621.  notch Filter Parsing Using/Walking Reader Walker Loading Loader navigates
  622.  object,
  623.   Filters
  624.  Annotations reflects
  625.  and
  626.  filters
  627. Taking
  628.  it
  629.  up
  630.  a
  631.  notch Filter Parsing Using/Walking Reader Walker Loading Loader annotations navigates
  632.  object,
  633.   Filters
  634.  Annotations reflects
  635.  and
  636.  filters
  637. Taking
  638.  it
  639.  up
  640.  a
  641.  notch Filter Parsing Using/Walking Reader Walker Loading Loader annotations metadata navigates
  642.  object,
  643.   Filters
  644.  Annotations reflects
  645.  and
  646.  filters
  647. /** * @MyAnnotation(“name”, nullable=true) */
  648. defaultProperty/** * @MyAnnotation(“name”, nullable=true) */

×