simplify your code with annotations - symfonycon warsaw 2013

71
/** * @SIMPLIFY YOUR CODE * WITH ANNOTATIONS **/ Created by / Piotr Pasich @piotrpasich

Upload: piotr-pasich

Post on 29-Nov-2014

1.307 views

Category:

Technology


0 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Simplify your code with annotations - SymfonyCon Warsaw 2013

/** * @SIMPLIFY YOUR CODE * WITH ANNOTATIONS**/

Created by / Piotr Pasich @piotrpasich

Page 2: Simplify your code with annotations - SymfonyCon Warsaw 2013

WWW.XSOLVE.PL @XSOLVE

Page 3: Simplify your code with annotations - SymfonyCon Warsaw 2013
Page 4: Simplify your code with annotations - SymfonyCon Warsaw 2013
Page 5: Simplify your code with annotations - SymfonyCon Warsaw 2013
Page 6: Simplify your code with annotations - SymfonyCon Warsaw 2013

„I HATE A LONG DISTANCEBETWEEN YOU AND ME”

ENTITY

Page 7: Simplify your code with annotations - SymfonyCon Warsaw 2013
Page 8: Simplify your code with annotations - SymfonyCon Warsaw 2013

LET’S START WRITING A STORY

Page 9: Simplify your code with annotations - SymfonyCon Warsaw 2013
Page 10: Simplify your code with annotations - SymfonyCon Warsaw 2013
Page 11: Simplify your code with annotations - SymfonyCon Warsaw 2013
Page 12: Simplify your code with annotations - SymfonyCon Warsaw 2013
Page 13: Simplify your code with annotations - SymfonyCon Warsaw 2013
Page 14: Simplify your code with annotations - SymfonyCon Warsaw 2013
Page 15: Simplify your code with annotations - SymfonyCon Warsaw 2013

/** * Edits an existing Post entity. * * @Route("/{id}", name="post_update") * @Method("PUT") * @Template("XsolveSymfonyConBundle:Post:edit.html.twig") */public function updateAction(Request $request, $id){ $em = $this->getDoctrine()->getManager();

$entity = $em->getRepository('XsolveSymfonyConBundle:Post')->find($id);

if (!$entity) { throw $this->createNotFoundException('Unable to find Post entity.'); }

$deleteForm = $this->createDeleteForm($id); $editForm = $this->createEditForm($entity); $editForm->handleRequest($request);

if ($editForm->isValid()) { $em->flush();

return $this->redirect($this->generateUrl('post_edit', array('id' => $id))); }

return array( 'entity' => $entity, 'edit_form' => $editForm->createView(), 'delete_form' => $deleteForm->createView(), );}

Page 16: Simplify your code with annotations - SymfonyCon Warsaw 2013

WELL, WE ARE NOTTHE BEST WRITERS,

ARE WE?

Page 17: Simplify your code with annotations - SymfonyCon Warsaw 2013

@ROUTE

Page 18: Simplify your code with annotations - SymfonyCon Warsaw 2013
Page 19: Simplify your code with annotations - SymfonyCon Warsaw 2013
Page 20: Simplify your code with annotations - SymfonyCon Warsaw 2013
Page 21: Simplify your code with annotations - SymfonyCon Warsaw 2013

/*** @Route("/{id}", name="post_update")* @Method("PUT")**/

Page 22: Simplify your code with annotations - SymfonyCon Warsaw 2013

class Route{ private $path; private $name; private $requirements = array(); private $options = array(); private $defaults = array(); private $host; private $methods = array(); private $schemes = array(); private $condition; /**(...)**/}

Page 23: Simplify your code with annotations - SymfonyCon Warsaw 2013

/*** @Route("/{id}", name="post_update",* methods="PUT"* requirements={"id" = "\d+"} )**/

Page 24: Simplify your code with annotations - SymfonyCon Warsaw 2013

@TEMPLATE

Page 25: Simplify your code with annotations - SymfonyCon Warsaw 2013

/*** @Template( "XsolveSymfonyConBundle:Post:edit.html.twig")**/

Page 26: Simplify your code with annotations - SymfonyCon Warsaw 2013

class Template{ private $template; private $engine = ’ twig’; private $vars = array(); private $streamable = false; /**(...)**/}

Page 27: Simplify your code with annotations - SymfonyCon Warsaw 2013

if ( ! $this->get('security.context')->isGranted('ROLE_EDITOR')) { throw new AccessDeniedException(); }

Page 28: Simplify your code with annotations - SymfonyCon Warsaw 2013

@SECURITY

Page 29: Simplify your code with annotations - SymfonyCon Warsaw 2013

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;

/** * @Security("has_role('ROLE_EDITOR')") */

Page 30: Simplify your code with annotations - SymfonyCon Warsaw 2013

public function updateAction(Request $request, $id){ $em = $this->getDoctrine()->getManager(); $entity = $em->getRepository('XsolveSymfonyConBundle:Post')->find($id); if (!$entity) { throw $this->createNotFoundException('Unable to find Post entity.'); }}

Page 31: Simplify your code with annotations - SymfonyCon Warsaw 2013

@PARAMCONVERTER

Page 32: Simplify your code with annotations - SymfonyCon Warsaw 2013

use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;

/** * @ParamConverter("post", class="XsolveSymfonyConBundle:Post") */ public function updateAction(Request $request, Post $post) {}

Page 33: Simplify your code with annotations - SymfonyCon Warsaw 2013

class ParamConverter{ private $name; private $class; private $options = array(); private $optional = false;}

Page 34: Simplify your code with annotations - SymfonyCon Warsaw 2013

/** * @Route("/blog/{date}/{slug}/")* @ParamConverter("post", options={"exclude": {"date"}})* @ParamConverter("post", class=" XsolveSymfonyConBundle:Post") , options={ "mapping": {"date": "date", "slug": "slug"}, "repository_method" = "findWithJoins"} }*/

Page 35: Simplify your code with annotations - SymfonyCon Warsaw 2013

YOUR OWNPARAMCONVERTER

Page 36: Simplify your code with annotations - SymfonyCon Warsaw 2013

namespace Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface;use Symfony\Component\HttpFoundation\Request;

interface ParamConverterInterface{ function apply(Request $request, ConfigurationInterface $configuration);

function supports(ConfigurationInterface $configuration);}

Page 37: Simplify your code with annotations - SymfonyCon Warsaw 2013

namespace XSolve\SymfonyConBundle\Request\ParamConverter;

use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterInterface;

class WebserviceParamConverter implements ParamConverterInterface{ protected $webservice; public function __contruct(Webservice $webservice){ $this->webservice = $webservice; } public function apply(Request $request, ParamConverter $configuration) { $name = $configuration->getName(); //The attribute name $class = $configuration->getClass(); //The attribute class name $options = $this->getOptions($configuration); //An array of options

$obj = $this->webservice->find($options['id']);

$request->attributes($param, $obj);

return true; }

public function supports(ConfigurationInterface $configuration) { $options = $this->getOptions($configuration);

return $this->webservice->find($options['id']) != null; }}

Page 38: Simplify your code with annotations - SymfonyCon Warsaw 2013

# app/config/config.ymlservices: webservice.param.converter class: XSolve\SymfonyConBundle\Request\ParamConverter\WebserviceParamConverter arguments: - @webservice tags: - { name: request.param_converter, priority: -2, converter: webserviceObj }

Page 39: Simplify your code with annotations - SymfonyCon Warsaw 2013

/*** @ParamConverter**/public function showAction(WebserviceObj $webserviceObj);

Page 40: Simplify your code with annotations - SymfonyCon Warsaw 2013

VALIDATION

Page 41: Simplify your code with annotations - SymfonyCon Warsaw 2013

protected $shortDescription;

protected $tags = array();

Page 42: Simplify your code with annotations - SymfonyCon Warsaw 2013

/** * @Assert\NotBlank() * @Assert\Length( * min = "2", * max = "250") */protected $shortDescription;

/** * @Assert\All({ * @Assert\NotBlank, * @Assert\Length(min = "1") * }) */protected $tags = array();

Page 43: Simplify your code with annotations - SymfonyCon Warsaw 2013

YOUR OWNVALIDATOR

Page 44: Simplify your code with annotations - SymfonyCon Warsaw 2013

namespace XSolve\SymfonyConBundle\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/** * @Annotation */class ContainsExample extends Constraint{ public $message = 'The example is not valid.';}

Page 45: Simplify your code with annotations - SymfonyCon Warsaw 2013

use XSolve\SymfonyConBundle\Validator\Constraints as SymfonyCon;

class ExampleEntity{ // ...

/** * @SymfonyCon\ContainsExample */ protected $property;

// ...}

Page 46: Simplify your code with annotations - SymfonyCon Warsaw 2013

$this->updateDate = new DateTime();

Page 47: Simplify your code with annotations - SymfonyCon Warsaw 2013

@ORM\PREPERSIST()@ORM\PREUPDATE()

Page 48: Simplify your code with annotations - SymfonyCon Warsaw 2013

/** * @ORM\Entity * @ORM\HasLifecycleCallbacks */ class Post { /** * @ORM\PrePersist() * @ORM\PreUpdate() */ public function preUpdate(){/*(...)*/}}

Page 49: Simplify your code with annotations - SymfonyCon Warsaw 2013

NOTIFICATIONS

Page 50: Simplify your code with annotations - SymfonyCon Warsaw 2013

SERVICES

Page 51: Simplify your code with annotations - SymfonyCon Warsaw 2013

JMSDIEXTRABUNDLEHTTP://JMSYST.COM/BUNDLES/JMSDIEXTR

ABUNDLE/MASTER/ANNOTATIONS

Page 52: Simplify your code with annotations - SymfonyCon Warsaw 2013

/** * @Service * @Tag("doctrine.event_listener", attributes = {"event" = "postUpdate"})*/class MailNotificationService { /** * @InjectParams({ * "mailer" = @Inject("mailer") * }) */ public function __construct(Swift_Mailer $mailer) { /*(...)*/}

public function postUpdate(LifecycleEventArgs $args) { /*(...) */}}

Page 53: Simplify your code with annotations - SymfonyCon Warsaw 2013

public function postUpdate(LifecycleEventArgs $args) { $entity = $args->getEntity(); if ($entity instanceof Post) { /** send notification **/ }}

Page 54: Simplify your code with annotations - SymfonyCon Warsaw 2013

PERFORMANCE

Page 55: Simplify your code with annotations - SymfonyCon Warsaw 2013

@CACHE (+ VARNISH + ESI)

Page 56: Simplify your code with annotations - SymfonyCon Warsaw 2013

public function showAction(Request $request, Post $post) { $response = new Response(); $response->setLastModified($post->getUpdatedAt()); if ($response->isNotModified($request)) { return $response; } $response->setExpires("tomorrow"); $response->setMaxAge(600); $response->setSharedMaxAge(600); $response->setPublic(true);

return $response;}

Page 57: Simplify your code with annotations - SymfonyCon Warsaw 2013

/** * @Cache(expires="tomorrow", public="true") */ public function showAction(Post $post) {/**(...)**/}

Page 58: Simplify your code with annotations - SymfonyCon Warsaw 2013

CONCLUSION

Page 59: Simplify your code with annotations - SymfonyCon Warsaw 2013

BEFORE

Page 60: Simplify your code with annotations - SymfonyCon Warsaw 2013

/** * Edits an existing Post entity. * * @Route("/{id}", name="post_update") * @Method("PUT") * @Template("XsolveSymfonyConBundle:Post:edit.html.twig") */public function updateAction(Request $request, $id){ if ( ! $this->get('security.context')->isGranted('ROLE_EDITOR')) { throw new AccessDeniedException(); }

$em = $this->getDoctrine()->getManager();

$entity = $em->getRepository('XsolveSymfonyConBundle:Post')->find($id);

if (!$entity) { throw $this->createNotFoundException('Unable to find Post entity.'); }

$deleteForm = $this->createDeleteForm($id); $editForm = $this->createEditForm($entity); $editForm->handleRequest($request);

if ($editForm->isValid()) { $entity->setUpdateDate(new DateTime()); $em->flush();

try { $this->get('xsolve.email.notificator')->send($entity); } catch (Exception $e) { $this->get('session')->getFlashBag()

Page 61: Simplify your code with annotations - SymfonyCon Warsaw 2013

AFTER

Page 62: Simplify your code with annotations - SymfonyCon Warsaw 2013

/** * @Route("/{id}", name="post_update", methods="PUT") * @Template("XsolveSymfonyConBundle:Post:edit.html.twig") * @ParamConverter * @Security("has_role('ROLE_EDITOR')") */public function updateAction(Request $request, Post $post){ $deleteForm = $this->createDeleteForm($post->getId()); $editForm = $this->createEditForm($post); $editForm->handleRequest($request);

if ($editForm->isValid()) { $em->flush();

return $this->redirect($this->generateUrl('post_edit', array('id' => $id))); }

return array( 'entity' => $entity, 'edit_form' => $editForm->createView(), 'delete_form' => $deleteForm->createView(), );}

Page 63: Simplify your code with annotations - SymfonyCon Warsaw 2013

@ANNOTATION

Page 64: Simplify your code with annotations - SymfonyCon Warsaw 2013

namespace XSolve\SymfonyConBundle\Annotation; /** * @Annotation */class SwitchLight{ private $room;

public function setRoom($room) { $this->room = $room; }

public function getRoom($room) { return $this->room; }}

Page 65: Simplify your code with annotations - SymfonyCon Warsaw 2013

namespace XSolve\SymfonyConBundle\Annotation\Driver; use XSolve\SymfonyConBundle\Annotation\SwitchLight;

/** * @Annotation */class AnnotationDriver{ private $reader;

private $roomLight; public function __construct($reader, Light $roomLight) { $this->reader = $reader;//get annotations reader $this->roomLight = $roomLight; } public function onKernelController(FilterControllerEvent $event) { if (!is_array($controller = $event->getController())) { //return if no controller return; }

$object = new \ReflectionObject($controller[0]);// get controller $method = $object->getMethod($controller[1]);// get method foreach ($this->reader->getMethodAnnotations($method) as $configuration) { //Start of annotations reading if(is_object($configuration) && $configuration instanceof SwitchLight)){//Found our annotation $this->roomLight->switch($configuration->getRoom()); } }}

Page 66: Simplify your code with annotations - SymfonyCon Warsaw 2013

services: some_annotation_driver: class: XSolve\SymfonyConBundle\Annotation\Driver\AnnotationDriver tags: [{name: kernel.event_listener, event: kernel.controller, method: onKernelController}] arguments: [@annotation_reader, @room_light]

Page 67: Simplify your code with annotations - SymfonyCon Warsaw 2013

/*** @SwitchLight(room="salon")*/public function switchLightInSalonAction(){...}

Page 68: Simplify your code with annotations - SymfonyCon Warsaw 2013

Q&ATHANK YOU

Page 69: Simplify your code with annotations - SymfonyCon Warsaw 2013

NO QUESTIONS?

Page 70: Simplify your code with annotations - SymfonyCon Warsaw 2013

SHOULD WE CREATE AN ANNOTATION

FOR BREADCRUMBS?

Page 71: Simplify your code with annotations - SymfonyCon Warsaw 2013

WE'RE HIRINGXSOLVE.PL