RESTful avec symfony 1 et Symfony2
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

RESTful avec symfony 1 et Symfony2

on

  • 29,147 views

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. ...

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/

Statistics

Views

Total Views
29,147
Views on SlideShare
15,333
Embed Views
13,814

Actions

Likes
17
Downloads
346
Comments
2

25 Embeds 13,814

http://symfpony-project.org 9358
http://www.lafermeduweb.net 2803
http://www.willdurand.fr 743
http://www.symfony.es 270
http://willdurand.fr 158
http://blogdwich.fr 150
http://www.symfonylab.com 142
http://pocky.github.com 75
http://translate.googleusercontent.com 20
http://lanyrd.com 20
http://www.emmanuelpereira.com 15
http://webcache.googleusercontent.com 14
http://feeds.feedburner.com 14
http://pocky.github.io 7
http://www.sfexception.com 4
http://cache.baiducontent.com 4
http://symfony.es 3
http://pinterest.com 3
http://local.symfpony-project.org 3
http://www.linkedin.com 2
https://www.linkedin.com 2
http://m.lafermeduweb.net 1
http://static.slidesharecdn.com 1
http://feedproxy.google.com 1
http://www.pearltrees.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

CC Attribution-NonCommercial-ShareAlike LicenseCC Attribution-NonCommercial-ShareAlike LicenseCC Attribution-NonCommercial-ShareAlike License

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
  • hello ! I tried to do the example of encoding XML format with Symfony 2. It doesn't work :(
    Do you have any idea plz !! thank you :)
    Are you sure you want to
    Your message goes here
    Processing…
  • Do not forget to check out http://symfpony-project.org/ !
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

RESTful avec symfony 1 et Symfony2 Presentation Transcript

  • 1. RESTful avec symfony et Symfony2 Damien Alexandre, Xavier Lacot – 03 mars 2011Symfony Day – 4. Juni 2009Clever Age | Xavier Lacot
  • 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 2011Clever Age | Damien Alexandre, Xavier Lacot 2
  • 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 dexpertise  Vice-président de lAFUP  http://twitter.com/xavierlacotRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 3
  • 4. Sommaire  2 ou 3 rappels sur REST  symfony, un framework RESTFul  Et dans Symfony2 ?  howto  benchmarks  Autour de Symfony – Plugins et BundlesRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 4
  • 5. 2 ou 3 rappels sur RESTRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 5
  • 6. 2 ou 3 rappels sur REST  Développement dAPIs : de nombreux cas dutilisation :  favoriser linteropé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 2011Clever Age | Damien Alexandre, Xavier Lacot 6
  • 7. 2 ou 3 rappels sur REST  Un service Web  Un fournisseur (le « service »)  Un agent (le « client ») requête client service réponseRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 7
  • 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 ressourcesRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 8
  • 9. De lutilisation dHTTP avec REST  REST != HTTP  mais REST <3 HTTP :  les codes de réponse  les URL  les content-type  les méthodes Roy FieldingRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 9 http://www.flickr.com/photos/bblfish/637617442/
  • 10. De lutilisation dHTTP 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 dune ressource  OPTIONS : Obtenir les méthodes acceptésRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 10
  • 11. De lutilisation dHTTP avec REST  Les codes de succès :  200 : OK  201 : Créé  Les codes de redirection :  301 : Ressource déplacée  304 : Ressource non modifiéeRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 11
  • 12. De lutilisation dHTTP avec REST  Les codes derreur client :  400 : Bad Request  404 : Ressource introuvable  405 : Méthode non autorisé  406 : Non acceptable  418 : Im a teapot  Les codes derreur serveur :  500 : Erreur généraleRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 12
  • 13. De lutilisation dHTTP avec REST  LURL  Uniform Resource Locator  http://domaine.tld/ressource/id : Désigne une ressource  http://domaine.tld/ressource : Désigne toutes les ressourcesRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 13
  • 14. symfony 1, un framework RESTfulRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 14
  • 15. Introducing Pony !RESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 15
  • 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: falseRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 16
  • 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 2011Clever Age | Damien Alexandre, Xavier Lacot 17
  • 18. Le routing dans symfony 1  gérer le plan dadressage dune application symfony  jolies urls  obfuscation des technos employées  validation des paramètres passés  découpler les urls exposées de lorganisation interne du projet  routing.yml  plusieurs classes de routing  sfRequestRoute / sfPatternRoute / sfRouteCollection  sfDoctrineRoute / sfDoctrineRouteCollection  etc...RESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 18
  • 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 2011Clever Age | Damien Alexandre, Xavier Lacot 19
  • 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 2011Clever Age | Damien Alexandre, Xavier Lacot 20
  • 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 2011Clever Age | Damien Alexandre, Xavier Lacot 21
  • 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 2011Clever Age | Damien Alexandre, Xavier Lacot 22
  • 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/jsonRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 23
  • 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 dobjets...RESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 24
  • 25. RESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 25
  • 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 2011Clever Age | Damien Alexandre, Xavier Lacot 26
  • 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 compliantRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 27
  • 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 lAPI sur un appel à lurl 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 payloadRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 28
  • 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 2011Clever Age | Damien Alexandre, Xavier Lacot 29
  • 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 dApache – mod_cband http://codee.pl/cband.htmlRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 30
  • 31. Authentification dAPI par api_key  ajout dun paramètre à chaque requête  dans lurl  ou en header http  approche dite "naïve" :  pas très sécurisée (man in the middle = le secret est connu)  mode dauthentification persistant dans le temps (clé compromise → changement de clé)RESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 31
  • 32. Authentification dAPI 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 2011Clever Age | Damien Alexandre, Xavier Lacot 32
  • 33. Authentification dAPI par OAuth  OAuth :  plus robuste et rassurant  plus long à mettre en place  protocole adapté à la gestion de lauthentification sur APIsRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 33
  • 34. Authentification dAPI 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 lAPI (token) réponse (donnée demandée)RESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 34
  • 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: trueRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 35
  • 36. Gestion du cache  Bootstrap = config, plugins, config BDD, routing, autoloading, session...RESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 36
  • 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 2011Clever Age | Damien Alexandre, Xavier Lacot 37
  • 38. Et avec Symfony2 ?RESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 38
  • 39. Pony2, des poneys en Doctrine2  entité Doctrine2 = modèle Doctrine 1  définition du schéma en PHP, yml ou XML  aussi possible à laide des annotations  pas dhé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 2011Clever Age | Damien Alexandre, Xavier Lacot 39
  • 40. Pony2, des poneys en Doctrine2  les annotations permettent dindiquer à 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 2011Clever Age | Damien Alexandre, Xavier Lacot 40
  • 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. 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 2011Clever Age | Damien Alexandre, Xavier Lacot 42
  • 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 2011Clever Age | Damien Alexandre, Xavier Lacot 43
  • 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 $ponyClever Age | Damien Alexandre, Xavier Lacot 44 }
  • 45. Serializer component Finally !RESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 45
  • 46. Les “normalizers”  Transformation ressource → array  CustomNormalizer  normalize() et denormalize() sont implémentées sur lobjet  GetSetMethodNormalizer  inspecte les getters et les setters de lobjetRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 46
  • 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 2011Clever Age | Damien Alexandre, Xavier Lacot 47
  • 48. Implémentation de CustomNormalizeruse 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 2011Clever Age | Damien Alexandre, Xavier Lacot 48
  • 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 2011Clever Age | Damien Alexandre, Xavier Lacot 49
  • 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 2011Clever Age | Damien Alexandre, Xavier Lacot 50
  • 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 2011Clever Age | Damien Alexandre, Xavier Lacot 51
  • 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 2011Clever Age | Damien Alexandre, Xavier Lacot 52
  • 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 2011Clever Age | Damien Alexandre, Xavier Lacot 53
  • 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 2011Clever Age | Damien Alexandre, Xavier Lacot 54
  • 55. Cache HTTP  Le cache est vérifié avant dinstancier le framework. gateway cache, ou reverse proxyRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 55
  • 56. Cache HTTP  Le cache est vérifié avant dinstancier le framework. gateway cache, ou reverse proxy ou ou Symfony2 HttpCacheRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 56
  • 57. Expiration du cache HTTP $response = new Response(); $response->setPublic(); $response->setSharedMaxAge(600);  Comme pour symfony1 mais sans invalidation.  Impossible dinvalider programmatiquement le cache  Possible de définir une durée de vieRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 57
  • 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 2011Clever Age | Damien Alexandre, Xavier Lacot 58
  • 59. Les très nécessaires benchmarksRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 59
  • 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 à laide de siege - http://www.joedog.org/index/siege-homeRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 60
  • 61. Résultats bruts  Lecture :  rel = rapport au moins performant,  avg = requêtes par seconde, en moyenne sur les 3 runsframework | rel | avg | 1 | 2 | 3------------------------ | -------- | -------- | -------- | -------- | --------Symfony2Cache | 9.6251 | 373.87 | 369.49 | 373.75 | 378.36symfony1Cache | 2.2480 | 87.32 | 86.25 | 87.78 | 87.94Symfony2ProdJson | 1.7970 | 69.80 | 69.64 | 70.71 | 69.04Symfony2ProdXml | 1.6106 | 62.56 | 60.92 | 62.73 | 64.03symfony1Prod | 1.2769 | 49.60 | 48.41 | 50.60 | 49.80Symfony2Dev | 1.1467 | 44.54 | 43.43 | 44.09 | 46.09symfony1Dev | 1.0000 | 38.84 | 37.85 | 40.90 | 37.78RESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 61
  • 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 configurationRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 62
  • 63. Traces Xdebug et XHProf Nos premiers tests : Symfony2 était plus lent que symfony 1RESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 63
  • 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 dexécution avec graphviz  https://github.com/facebook/xhprofRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 64
  • 65. Traces Xdebug et XHProf Vraiment ? Regardons la trace XHProfRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 65
  • 66. Traces Xdebug et XHProf  Annotations Doctrine parsées à chaque requête ! # app/config/config.yml doctrine: orm: metadata_cache_driver: apcRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 66
  • 67. Traces Xdebug et XHProf  Après :RESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 67
  • 68. Encore plus parlant avec XDebugRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 68
  • 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: apcRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 69
  • 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 dannotations : 3 027 240 b  Symfony2 mode prod sans cache HTTP : 2 800 600 b  Symfony2 mode prod avec cache HTTP : 1 012 496 bRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 70
  • 71. Autour de SymfonyRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 71
  • 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 2011Clever Age | Damien Alexandre, Xavier Lacot 72
  • 73. Des bundles pour Symfony2  EverzetRestfulControllersBundle  création automatique des routes à partir de noms dactions  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. Pour conclure... REST cest bien. Et avec symfony cest facile. Avec Symfony2, cest encore mieux. http://symfpony-project.org/ https://github.com/xavierlacot/symfpony-project.org https://github.com/xavierlacot/symfpony-benchmarkRESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 74
  • 75. Time to REST Des questions ?RESTful avec symfony 1 et Symfony2 – 3 mars 2011Clever Age | Damien Alexandre, Xavier Lacot 75
  • 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 2011Clever Age | Damien Alexandre, Xavier Lacot 76