Successfully reported this slideshow.

RESTful avec symfony 1 et Symfony2

19

Share

Loading in …3
×
1 of 76
1 of 76

RESTful avec symfony 1 et Symfony2

19

Share

Download to read offline

These slides describe how symfony 1 and Symfony2 are RESTful frameworks, and ho to implement RESTful web services in both. The talk was given during Symfony Live 2011 Paris.

For more informations, please see http://symfpony-project.org/

These slides describe how symfony 1 and Symfony2 are RESTful frameworks, and ho to implement RESTful web services in both. The talk was given during Symfony Live 2011 Paris.

For more informations, please see http://symfpony-project.org/

More Related Content

Related Books

Free with a 14 day trial from Scribd

See all

Related Audiobooks

Free with a 14 day trial from Scribd

See all

RESTful avec symfony 1 et Symfony2

  1. 1. RESTful avec symfony et Symfony2 Damien Alexandre, Xavier Lacot – 03 mars 2011 Symfony Day – 4. Juni 2009 Clever Age | Xavier Lacot
  2. 2. Clever Age  Création en 2001 à Paris par des managers expérimentés  Plusieurs agences en France :  Paris  Bordeaux  Lyon  Nantes  Valeurs fondatrices : Indépendance, Veille technologique, Conviction  Quelques chiffres :  CA 2009 : 6 M€  Effectif au 01/03/2011 : 90 personnes  Notre Mission : « Concevoir des systèmes informatiques flexibles en limitant la dépendance vis-à-vis des prestataires et des éditeurs » RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 2
  3. 3. Qui sommes nous ?  Damien :  Spécialiste Web full stack  Plusieurs contributions, notamment à symfony  Expert technique PHP chez Clever Age  Éleveur de poneys  http://twitter.com/damienalexandre  Xavier :  Expert Frameworks, développeur symfony depuis fin 2005  Plusieurs contributions (plugins, doc, patches, etc.)  Leader PHP chez Clever Age + en charge du pôle d'expertise  Vice-président de l'AFUP  http://twitter.com/xavierlacot RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 3
  4. 4. Sommaire  2 ou 3 rappels sur REST  symfony, un framework RESTFul  Et dans Symfony2 ?  howto  benchmarks  Autour de Symfony – Plugins et Bundles RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 4
  5. 5. 2 ou 3 rappels sur REST RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 5
  6. 6. 2 ou 3 rappels sur REST  Développement d'APIs : de nombreux cas d'utilisation :  favoriser l'interopérabilité  contextes répartis  plusieurs applications différentes  plusieurs langages  exposer un référentiel de données  exposer des données publiques (OpenData, etc.) RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 6
  7. 7. 2 ou 3 rappels sur REST  Un service Web  Un fournisseur (le « service »)  Un agent (le « client ») requête client service réponse RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 7
  8. 8. REST et SOAP sont sur un bateau  REST  Representational state transfer  exposition de ressources  "colle" à HTTP  simple et compréhensible  WS-*  SOAP + WSDL  approche plus standardisée  plus verbeux  moins adapté à la description de ressources RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 8
  9. 9. De l'utilisation d'HTTP avec REST  REST != HTTP  mais REST <3 HTTP :  les codes de réponse  les URL  les content-type  les méthodes Roy Fielding RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 9 http://www.flickr.com/photos/bblfish/637617442/
  10. 10. De l'utilisation d'HTTP avec REST  Les verbes :  GET : Obtenir une ressource  POST + http content : Créer une ressource  PUT + http content : Modifier une ressource  DELETE : Supprimer une ressource  HEAD : Obtenir les headers d'une ressource  OPTIONS : Obtenir les méthodes acceptés RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 10
  11. 11. De l'utilisation d'HTTP avec REST  Les codes de succès :  200 : OK  201 : Créé  Les codes de redirection :  301 : Ressource déplacée  304 : Ressource non modifiée RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 11
  12. 12. De l'utilisation d'HTTP avec REST  Les codes d'erreur client :  400 : Bad Request  404 : Ressource introuvable  405 : Méthode non autorisé  406 : Non acceptable  418 : I'm a teapot  Les codes d'erreur serveur :  500 : Erreur générale RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 12
  13. 13. De l'utilisation d'HTTP avec REST  L'URL  Uniform Resource Locator  http://domaine.tld/ressource/id : Désigne une ressource  http://domaine.tld/ressource : Désigne toutes les ressources RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 13
  14. 14. symfony 1, un framework RESTful RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 14
  15. 15. Introducing Pony ! RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 15
  16. 16. Ressource Pony Pony Pony: id integer columns: name: name string(255) type: string(255) picture_url string(255) picture_url: type: string(255) description text description: slug string(255) type: text actAs: Sluggable: unique: true fields: [name] canUpdate: false RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 16
  17. 17. Ressource Pony  New forest => new-forest  Magic Pony => magic-pony  GET http://domain.tld/pony/new-forest.xml ou  GET http://domain.tld/pony/8.xml  Le routing décide. RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 17
  18. 18. Le routing dans symfony 1  gérer le plan d'adressage d'une application symfony  jolies urls  obfuscation des technos employées  validation des paramètres passés  découpler les urls exposées de l'organisation interne du projet  routing.yml  plusieurs classes de routing  sfRequestRoute / sfPatternRoute / sfRouteCollection  sfDoctrineRoute / sfDoctrineRouteCollection  etc... RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 18
  19. 19. sfDoctrineRoute  routing.yml pony_show: url: /pony/:slug.:sf_format param: { module: pony, action: show, sf_format: xml } class: sfDoctrineRoute options: { model: Pony, column: slug, type: object } requirements: { sf_method: GET, sf_format: (xml|json|yml) }  actions.class.php public function executeShow(sfWebRequest $request) { $pony = $this->getRoute()->getObject(); // etc. } RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 19
  20. 20. Routing et format  sf_format est html par défaut pony_show: url: /pony/:slug.:sf_format param: { module: pony, action: show, sf_format: xml } class: sfDoctrineRoute options: { model: Pony, column: slug, type: object } requirements: { sf_method: GET, sf_format: (xml|json|yml) }  actions.class.php public function executeShow(sfWebRequest $request) { $format = $request->getRequestFormat(); // etc. } RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 20
  21. 21. Les formats GET http://domain/pony/new-forest.xml <?xml version="1.0" encoding="UTF-8" standalone="no" ?> <response> <name><![CDATA[New Forest]]></name> <picture_url> <![CDATA[http://www.feracheval.com/nvxsite/newforest.jpg]]> </picture_url> <description> <![CDATA[Le poney New-Forest...]]> </description> <slug><![CDATA[new-forest]]></slug> </response> RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 21
  22. 22. Les formats GET http://domain/pony/new-forest.json { "name": "New Forest", "picture_url": "http://www.feracheval.com/nvxsite/newforest.jpg", "description": "Le poney New-Forest...", "slug": "new-forest" } RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 22
  23. 23. Format et template  Le template utilisé change suivant sf_format :  html => showSuccess.php  xml => showSuccess.xml.php  json => showSuccess.json.php  Content-Type automatique pour les formats suivants :  txt, js, css, json, xml, rdf, atom.  Exemple :  GET http://domain/pony/connemara.json  Content-Type: application/json RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 23
  24. 24. Format et template  showSuccess.json.php { "name": <?php echo json_encode($pony->getName()) ?>, "picture_url": <?php echo json_encode($pony->getPictureUrl(ESC_RAW)) ?>, "description": <?php echo json_encode($pony->getDescription(ESC_RAW)) ?>, "slug": <?php echo json_encode($pony->getSlug())."n" ?> }  Bon courage pour les listes d'objets... RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 24
  25. 25. RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 25
  26. 26. Format sans template  Sans template, on spécifie le Content-Type à la main : $format = $request->getRequestFormat(); $this->getResponse()->setContentType( $request->getMimeType($format) ); return sfView::NONE;  La solution consiste à employer un Serializer...  Pas de serializer dans symfony 1  Pas de serializer XML dans Zend  Doctrine peut le faire pour vous : $this->getResponse()->setContent( $query->execute()->exportTo($format) ); RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 26
  27. 27. Format sans template  Le cas particulier de json... $this->getResponse()->setContent( json_encode($pony->toArray()) );  facile  plus rapide (natif)  écriture compacte (moins verbeux que XML)  Cool pour la bande passante  Javascript compliant RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 27
  28. 28. Validation des paramètres  Exposer une interface = nécessité de valider les entrées  en GET : valider les restrictions  http://api.domain.tld/pony.json?country=france  que doit faire l'API sur un appel à l'url suivante ? http://api.domain.tld/pony.json?speaks=german  en écriture (POST / PUT) :  valider la présence du payload (HTTP content)  format attendu  contenu du payload RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 28
  29. 29. Validation des paramètres  symfony 1 offre une série complète de validateurs  Email  Url  Date  etc. public function executeShow(sfWebRequest $request) { $name = $request->getParameter('name'); $validator = new sfValidatorString(array('required' => true)); // throws an exception if not valid $cleaned = $validator->clean($name) // etc. } RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 29
  30. 30. REST en haute Sécurité  Plusieurs approches de la sécurité :  qui a accès (authentification) ?  à quel rythme / fréquence (throttling) ?  Authentification :  approche naïve par preExecute  approche OAuth  Throttling  aidez vous d'Apache – mod_cband http://codee.pl/cband.html RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 30
  31. 31. Authentification d'API par api_key  ajout d'un paramètre à chaque requête  dans l'url  ou en header http  approche dite "naïve" :  pas très sécurisée (man in the middle = le secret est connu)  mode d'authentification persistant dans le temps (clé compromise → changement de clé) RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 31
  32. 32. Authentification d'API par api_key class ponyApiActions extends sfActions { public function preExecute() { $request = $this->getRequest(); $key = $request->getParameter('ApiKey'); if (!Doctrine::getTable('ApiKey')->findOneByApiKey($key)) { $this->getResponse()->setStatusCode(401); throw new sfException('Invalid authentication credentials.'); } } // etc } RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 32
  33. 33. Authentification d'API par OAuth  OAuth :  plus robuste et rassurant  plus long à mettre en place  protocole adapté à la gestion de l'authentification sur APIs RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 33
  34. 34. Authentification d'API par OAuth redirection vers page de login Application cliente réponse (code) Passage du code API getToken (code) REST réponse (token) Application serveur appel de l'API (token) réponse (donnée demandée) RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 34
  35. 35. Gestion du cache  Du cache sur une API ?  Oui, même de courte durée  cache.yml default: enabled: true with_layout: true lifetime: 120 # 2 minutes cache  settings.yml prod: .settings: cache: true RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 35
  36. 36. Gestion du cache  Bootstrap = config, plugins, config BDD, routing, autoloading, session... RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 36
  37. 37. Gestion du cache  Invalidation du cache if ($cache = $this->getContext()->getViewCacheManager()) { $cache->remove('pony/index'); $cache->remove('pony/show?slug='.$slug); } RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 37
  38. 38. Et avec Symfony2 ? RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 38
  39. 39. Pony2, des poneys en Doctrine2  entité Doctrine2 = modèle Doctrine 1  définition du schéma en PHP, yml ou XML  aussi possible à l'aide des annotations  pas d'héritage de Doctrine_Record :  src/CleverAge/SymfponyBundle/Entity/Pony.php class Pony { protected $id; protected $name; protected $picture_url; protected $description; protected $slug; } RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 39
  40. 40. Pony2, des poneys en Doctrine2  les annotations permettent d'indiquer à Doctrine comment persister les données /** * @orm:Table(name="pony") * @orm:Entity */ class Pony { /** * @orm:Column(name="id", type="integer") * @orm:Id * @orm:GeneratedValue(strategy="IDENTITY") */ protected $id; /** * @orm:Column(name="name", type="string", length=110) */ protected $name; // etc. RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 40
  41. 41. Pony2 - Générer getter et setters $ php app/console doctrine:generate:entities CleverAgeSymfponyBundle Generating entities for "CleverAgeSymfponyBundle" > generating CleverAgeSymfponyBundleEntityPony /** * Get id * @return integer $id */ public function getId() { return $this->id; } /** * Set name * @param string $name */ public function setName($name) { $this->name = $name; RESTful avec symfony 1 et Symfony2 – 3 mars 2011 } Clever Age | Damien Alexandre, Xavier Lacot 41
  42. 42. Le routing avec Symfony2  app/config/routing.yml : symfpony: resource: "@CleverAgeSymfponyBundle/Resources/config/routing.yml"  src/CleverAge/SymfponyBundle/Resources/config/routing.yml : pony_list: pattern: /pony.{_format} defaults: - _controller: CleverAgeSymfponyBundle:Default:index - _format: xml requirements: { _format: (xml|json), _method: GET } RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 42
  43. 43. Le routing avec Symfony2  Dumpable en RewriteRule Apache : $ php app/console router:dump-apache RewriteCond %{REQUEST_METHOD} ^(GET) [NC] RewriteCond %{PATH_INFO} ^/pony(?:.((xml|json)))?$ RewriteRule .* app.php [QSA,L,E=_ROUTING__route:pony_list,E=_ROUTING__format: %1,E=_ROUTING__controller:CleverAgeSymfponyBundleControllerDefaul tController::indexAction,E=_ROUTING__format:xml] RewriteCond %{REQUEST_METHOD} ^(GET) [NC] RewriteCond %{PATH_INFO} ^/pony/([a-z0-9-]+)(?:.((xml|json)))?$ RewriteRule .* app.php [QSA,L,E=_ROUTING__route:pony_show,E=_ROUTING_slug: %1,E=_ROUTING__format: %2,E=_ROUTING__controller:CleverAgeSymfponyBundleControllerDefaul tController::showAction,E=_ROUTING__format:xml] etc. RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 43
  44. 44. Le routing avec Symfony2  Pas de sfDoctrineRoute :'( pony_show: pattern: /pony/{slug}.{_format} Defaults: - _controller: CleverAgeSymfponyBundle:Default:show - _format: xml requirements: { _format: (xml|json), _method: GET, slug: "[a-z0-9-]+" }  Mais FrameworkExtraBundle est là...  http://bundles.symfony-reloaded.org/frameworkextrabundle/  ParamConverter FTW : /** * the Pony is automaticaly fetched by the ParamConverter. * @param Pony $pony * @param string $_format */ public function showAction(Pony $pony, $_format) { RESTful avec symfony do Symfony2 – 3 mars 2011 // 1 et what you want with $pony Clever Age | Damien Alexandre, Xavier Lacot 44 }
  45. 45. Serializer component Finally ! RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 45
  46. 46. Les “normalizers”  Transformation ressource → array  CustomNormalizer  normalize() et denormalize() sont implémentées sur l'objet  GetSetMethodNormalizer  inspecte les getters et les setters de l'objet RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 46
  47. 47. Les “encodeurs”  Transformation array → format  JsonEncoder  simple implémentation de json_encode  XmlEncoder  Utilisation de DOMDocument  [insérer un format ici]Encoder  Forkez moi ! RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 47
  48. 48. Implémentation de CustomNormalizer use SymfonyComponentSerializerNormalizerNormalizableInterface; use SymfonyComponentSerializerNormalizerNormalizerInterface; class Pony implements NormalizableInterface { function normalize(NormalizerInterface $normalizer, $format, $properties = null) { return array( 'name' => $this->getName(), 'picture_url' => $this->getPictureUrl(), 'description' => $this->getDescription(), 'slug' => $this->getSlug(), ); } // etc. } RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 48
  49. 49. Utilisation du Serializer $serializer = new SerializerSerializer(); $serializer->addNormalizer( new SerializerNormalizerCustomNormalizer() ); $serializer->setEncoder( 'xml', new SerializerEncoderXmlEncoder() ); $serializer->encode($pony, 'xml'); RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 49
  50. 50. Utilisation du Serializer <?xml version="1.0" encoding="UTF-8" standalone="no" ?> <response> <name><![CDATA[New Forest]]></name> <picture_url> <![CDATA[http://www.feracheval.com/nvxsite/newforest.jpg]]> </picture_url> <description> <![CDATA[Le poney New-Forest...]]> </description> <slug><![CDATA[new-forest]]></slug> </response> $xmlEncoder = new SerializerEncoderXmlEncoder(); $xmlEncoder->setRootNodeName('Pony'); RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 50
  51. 51. Validation des entrées  Comme avec symfony 1 :  Nécessaire de valider les entrées  Symfony2 fournit toute une série de validateurs  classes étendant SymfonyComponentValidatorConstraint  aussi complet que les validators symfony1  Doctrine2 ne fournit aucun validateur (par choix) RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 51
  52. 52. Déclaration des validateurs  Format de déclaration des validateurs au choix  YML  XML  PHP  annotations class Pony { /** * @validation:NotBlank() * @validation:MinLength(3) */ private $name; ... } RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 52
  53. 53. Exécution de la validation  activer le service de validation # app/config/config.yml framework: validation: enabled: true  valider dans le contrôleur $validator = $container->get('validator'); if (0 === count($validator->validate($pony))) { // persist the Pony } RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 53
  54. 54. Le cache dans Symfony2  Présentation de Fabien demain à 11h30  Sujet majeur !  Conférence pas trop tôt  Conférencier pas trop mauvais :-)  Quelques détails quand même... RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 54
  55. 55. Cache HTTP  Le cache est vérifié avant d'instancier le framework. gateway cache, ou reverse proxy RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 55
  56. 56. Cache HTTP  Le cache est vérifié avant d'instancier le framework. gateway cache, ou reverse proxy ou ou Symfony2 HttpCache RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 56
  57. 57. Expiration du cache HTTP $response = new Response(); $response->setPublic(); $response->setSharedMaxAge(600);  Comme pour symfony1 mais sans invalidation.  Impossible d'invalider programmatiquement le cache  Possible de définir une durée de vie RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 57
  58. 58. Validation du cache HTTP $response = new Response(); $response->setETag(md5(serialize($pony))); if ($response->isNotModified($request)) { return $response; // 304 } else { $response->setContent( $this->getSerializer($_format) ->encode($pony, $_format) ); return $response; }  Ressource expirée ? Le meilleur des deux mondes.  Etag modifié ? RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 58
  59. 59. Les très nécessaires benchmarks RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 59
  60. 60. Méthodologie  même service Pony au format json :  symfony 1 mode dev  symfony 1 mode prod sans cache  symfony 1 mode prod avec cache  Symfony2 mode dev  Symfony2 mode prod sans cache  Symfony2 mode prod sans cache (format XML)  Symfony2 mode prod avec cache HTTP (PHP)  mêmes fonctionnalités  mesures faites à l'aide de siege - http://www.joedog.org/index/siege-home RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 60
  61. 61. Résultats bruts  Lecture :  rel = rapport au moins performant,  avg = requêtes par seconde, en moyenne sur les 3 runs framework | rel | avg | 1 | 2 | 3 ------------------------ | -------- | -------- | -------- | -------- | -------- Symfony2Cache | 9.6251 | 373.87 | 369.49 | 373.75 | 378.36 symfony1Cache | 2.2480 | 87.32 | 86.25 | 87.78 | 87.94 Symfony2ProdJson | 1.7970 | 69.80 | 69.64 | 70.71 | 69.04 Symfony2ProdXml | 1.6106 | 62.56 | 60.92 | 62.73 | 64.03 symfony1Prod | 1.2769 | 49.60 | 48.41 | 50.60 | 49.80 Symfony2Dev | 1.1467 | 44.54 | 43.43 | 44.09 | 46.09 symfony1Dev | 1.0000 | 38.84 | 37.85 | 40.90 | 37.78 RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 61
  62. 62. Commentaires  Symfony2 + cache HTTP est  4,5 fois plus performant que symfony 1 avec cache  7 fois plus performant que Symfony2 en mode dev (avec profiler)  10 fois plus que symfony 1 en mode dev  Symfony2 sans cache : 40% de gains de perfs face à symfony 1  le profiler Symfony2 est génial mais couteux  Préférez json à XML pour vos APIs  Chiffres à prendre avec précaution  Framework pas terminé vs. Framework vieux de 5 ans  Attention à la configuration RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 62
  63. 63. Traces Xdebug et XHProf Nos premiers tests : Symfony2 était plus lent que symfony 1 RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 63
  64. 64. Traces Xdebug et XHProf  Xdebug  Kudos à Derick Rethans  Super outil depuis 2002  Traces exploitables par KcacheGrind ou WinCacheGrind  http://www.xdebug.org/  XHProf  Facebook, Mars 2009  Très pratique aussi  Interface Web de consultation des traces  Graphes d'exécution avec graphviz  https://github.com/facebook/xhprof RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 64
  65. 65. Traces Xdebug et XHProf Vraiment ? Regardons la trace XHProf RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 65
  66. 66. Traces Xdebug et XHProf  Annotations Doctrine parsées à chaque requête ! # app/config/config.yml doctrine: orm: metadata_cache_driver: apc RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 66
  67. 67. Traces Xdebug et XHProf  Après : RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 67
  68. 68. Encore plus parlant avec XDebug RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 68
  69. 69. Encore plus parlant avec XDebug Interprétation de la Query Parsing des annotations Doctrine # app/config/config.yml doctrine: orm: metadata_cache_driver: apc query_cache_driver: apc RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 69
  70. 70. Memory usage  memory_get_peak_usage()  symfony 1 mode dev : 4 581 856 b  symfony 1 mode prod sans cache : 4 282 944 b  symfony 1 mode prod avec cache : 3 335 688 b  Symfony2 mode dev : 3 567 632 b  Symfony2 mode prod sans cache d'annotations : 3 027 240 b  Symfony2 mode prod sans cache HTTP : 2 800 600 b  Symfony2 mode prod avec cache HTTP : 1 012 496 b RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 70
  71. 71. Autour de Symfony RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 71
  72. 72. Des plugins pour symfony 1  sfDoctrineRestGeneratorPlugin :  admin generator like (generator.yml)  Serialization  facile à étendre  Validation  complexe mais puissant  sfRestWebServicePlugin :  Super-module  Template  facile à mettre en place  route api/*  support de PUT hacké (POST et sf_method=PUT) RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 72
  73. 73. Des bundles pour Symfony2  EverzetRestfulControllersBundle  création automatique des routes à partir de noms d'actions  pas de lien avec le modèle (actions à développer)  https://github.com/everzet/EverzetRestfulControllersBundle # app/config/routing.yml ponys: type: restful resource: CleverAgeSymfponyBundleControllerPonysController class PonysController extends Controller [GET] { public function getPonyAction($slug) /pony/connemara { // etc. } [POST] public function postPonysAction() /ponys { RESTful avec symfony 1 et Symfony2 – 3 mars 2011 // etc. Clever Age | Damien Alexandre, Xavier Lacot } 73
  74. 74. Pour conclure... REST c'est bien. Et avec symfony c'est facile. Avec Symfony2, c'est encore mieux. http://symfpony-project.org/ https://github.com/xavierlacot/symfpony-project.org https://github.com/xavierlacot/symfpony-benchmark RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 74
  75. 75. Time to REST Des questions ? RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 75
  76. 76.  Récompense des projets Web innovants  HTML5  OpenData  Mobilité  etc.  Appel à candidatures : candidat_awards@clever-age.com  Détails sur http://awards.clever-age.com/ RESTful avec symfony 1 et Symfony2 – 3 mars 2011 Clever Age | Damien Alexandre, Xavier Lacot 76

×