Symfony2, Backbone.js     & socket.io    Symfony live Paris 2013         @guillaumepotier    guillaume@wisembly.com
app.wisembly.com/sfliveapp.wisembly.com/sflive
2011, Septemberapp.wisembly.com/sflive
MySQL                          PHPapp.wisembly.com/sflive
Twig                         Symfony 2                         Doctrine 2                          MySQL                  ...
Twig js                          jQuery                          Assetic                           Twig                   ...
Backbone.js                         Underscore.js                            Twig js                            jQuery    ...
Backbone.js                              Underscore.js                                 Twig js                            ...
Client  Serverapp.wisembly.com/sflive
Client                         Twig                REST                                Symfony 2  Server                  ...
Backbone.js                            Underscore.js  Client                          jQuery                              ...
Backbone.js                                  Underscore.js  Client                                jQuery                  ...
Users want fast & smooth SaaS appsapp.wisembly.com/sflive
Users want fast & smooth SaaS apps                 Users want multiplateform SaaS appsapp.wisembly.com/sflive
Users want fast & smooth SaaS apps              Users want multiplateform SaaS apps           Users want dynamic & interac...
Users want fast & smooth SaaS apps              Users want multiplateform SaaS apps           Users want dynamic & interac...
Users want fast & smooth SaaS apps              Users want multiplateform SaaS apps           Users want dynamic & interac...
app.wisembly.com/sflive
?app.wisembly.com/sflive
E L L                         H !                          N  O                           ?app.wisembly.com/sflive
app.wisembly.com/sflive
Nowadaysapp.wisembly.com/sflive
app.wisembly.com/sflive
small / lightweight / stableapp.wisembly.com/sflive
small / lightweight / stable                         easy to learn, easy to extendapp.wisembly.com/sflive
small / lightweight / stable                         easy to learn, easy to extend                               great res...
Models   Modelsapp.wisembly.com/sflive
Models       Models             Collections   Repositoriesapp.wisembly.com/sflive
Models       Models             Collections   Repositories                  Views    Controllersapp.wisembly.com/sflive
Models       Models             Collections   Repositories                  Views    Controllers              Templates   ...
Models       Models             Collections   Repositories                  Views    Controllers              Templates   ...
Models           Models             Collections       Repositories                  Views        Controllers              ...
FOSJsRouting BazingaExposeTranslation             JMSSerializer          FOSRestBundleapp.wisembly.com/sflive
FOSJsRouting BazingaExposeTranslation             JMSSerializer          FOSRestBundleapp.wisembly.com/sflive
1 - MAKE AN APIapp.wisembly.com/sflive
MUST READ           http://fr.slideshare.net/nachomartin/symfony-           javascript-combining-the-best-of-two-worldsapp...
ar tin                                    nacm                                   @                         Books = new    ...
ar tin                                    nacm                                   @                         Books = new    ...
ar tin                                    nacm                                   @                         events:        ...
ar tin                                    nacm                                   @                         events:        ...
/**                                         * @var integer $id                                         *                  ...
II - MAKE A GOOD                    REST APIapp.wisembly.com/sflive
MUST READ 2           http://williamdurand.fr/2012/08/02/rest-apis-           with-symfony2-the-right-wayapp.wisembly.com/...
JMSSerializer                              orapp.wisembly.com/sflive
JMSSerializer                                           or         class User implements UserInterface, EquatableInterface...
JMSSerializer                                           or         class User implements UserInterface, EquatableInterface...
FOSRestBundle                              orapp.wisembly.com/sflive
FOSRestBundle                                            or       /**         * @Route("{keyword}/quote/{id}", name="api3_...
FOSRestBundle                                            or       /**         * @Route("{keyword}/quote/{id}", name="api3_...
FOSRestBundle                                            or       /**         * @Route("{keyword}/quote/{id}", name="api3_...
FOSRestBundle                                            or       /**         * @Route("{keyword}/quote/{id}", name="api3_...
FOSRestBundle                                            or       /**         * @Route("{keyword}/quote/{id}", name="api3_...
FOSRestBundle                                            or       /**         * @Route("{keyword}/quote/{id}", name="api3_...
FOSRestBundle                                            or       /**         * @Route("{keyword}/quote/{id}", name="api3_...
Controller                    Entity Service       API Service                         Entity       EntityRepositoryapp.wi...
Use Validator and Form                                                                          ouac                      ...
/**         * @Route("event/{keyword}/poll/{id}", name="api3_poll_edit", requirements={"id"   = "d+"}, options={"expose"=t...
/**         * @Route("event/{keyword}/poll/{id}", name="api3_poll_edit", requirements={"id"   = "d+"}, options={"expose"=t...
/**         * @Route("event/{keyword}/poll/{id}", name="api3_poll_edit", requirements={"id"   = "d+"}, options={"expose"=t...
/**         * @Route("event/{keyword}/poll/{id}", name="api3_poll_edit", requirements={"id"   = "d+"}, options={"expose"=t...
/**         * @Route("event/{keyword}/poll/{id}", name="api3_poll_edit", requirements={"id"   = "d+"}, options={"expose"=t...
app.wisembly.com/sflive
app.wisembly.com/sflive
FOSJsRouting BazingaExposeTranslation             JMSSerializer          FOSRestBundleapp.wisembly.com/sflive
ar tin                                         nacm                                        @                         event...
ar tin                                       nacm                                      @                         events: {...
websocketData?                              Who sends what?                         Which port, which protocol?app.wisembl...
app.wisembly.com/sflive
FOSJsRouting BazingaExposeTranslation             JMSSerializer          FOSRestBundleapp.wisembly.com/sflive
Authenticate user against     PUSH serverapp.wisembly.com/sflive
Authenticate user against     PUSH server                            sessionToken                               domainapp....
Authenticate user against     PUSH server                                           sessionToken                          ...
Authenticate user against     PUSH server                                           sessionToken                          ...
Authenticate user against     PUSH server                         Authenticated!                              rights      ...
PUSH: The «Classic» way                            rightsapp.wisembly.com/sflive
PUSH: The «Classic» way                     REST                   sessionToken                      domain               ...
PUSH: The «Classic» way                     REST                   sessionToken                                  data     ...
PUSH: The «Classic» way                     REST                   sessionToken                                  data     ...
PUSH: The «Classic» way                                                  websocketData                     REST           ...
• Slow: HTTP ajax round-trip           • !DRY: Double front processing (Ajax / Push)           • Push server complexity: a...
PUSH: The «Wisembly» way                                                  websocketData                     REST          ...
PUSH: The «Wisembly» way                                                           websocketData                     REST ...
PUSH: The «Wisembly» way                                                            websocketData                     REST...
PUSH: The «Wisembly» way                                                                   websocketData                  ...
Push «surprises»app.wisembly.com/sflive
Push «surprises»      • Must find always opened portapp.wisembly.com/sflive
Push «surprises»      • Must find always opened port      • Websocket protocol must go through firewallsapp.wisembly.com/sflive
Push «surprises»      • Must find always opened port      • Websocket protocol must go through firewalls      • Push may dis...
app.wisembly.com/sflive
• 80 always opened, but websocket very               often blocked -> FAIL -> goto 443 w/ httpsapp.wisembly.com/sflive
• 80 always opened, but websocket very               often blocked -> FAIL -> goto 443 w/ https           • Implement disc...
The «Wisembly» way                         hashN: { eventName, args }app.wisembly.com/sflive
The «Wisembly» way                         hashN: { eventName, args }app.wisembly.com/sflive
The «Wisembly» way                                                                     hashN            hashN             ...
The «Wisembly» way                                       hashM   hashM                               hashN hashN: { eventN...
The «Wisembly» way                                                      hashM   hashM                                     ...
The «Wisembly» way                                                                  hashM   hashM                         ...
The «Wisembly» way                                                                  hashM   hashM                         ...
Great Ressources  http://fr.slideshare.net/nachomartin/symfony-javascript-  combining-the-best-of-two-worlds  http://willi...
@guillaumepotier   http://wisembly.com/en/about#jobsapp.wisembly.com/sflive
Any Questions ?app.wisembly.com/sflive
app.wisembly.com/sflive
Upcoming SlideShare
Loading in...5
×

Symfony2, Backbone.js & socket.io - SfLive Paris 2k13 - Wisembly

15,167

Published on

Wisembly experience sharing on building one-page js app w/ Backbone.js over Symfony2 REST API and socket.io push server.

Symfony2, Backbone.js & socket.io - SfLive Paris 2k13 - Wisembly

  1. 1. Symfony2, Backbone.js & socket.io Symfony live Paris 2013 @guillaumepotier guillaume@wisembly.com
  2. 2. app.wisembly.com/sfliveapp.wisembly.com/sflive
  3. 3. 2011, Septemberapp.wisembly.com/sflive
  4. 4. MySQL PHPapp.wisembly.com/sflive
  5. 5. Twig Symfony 2 Doctrine 2 MySQL PHPapp.wisembly.com/sflive
  6. 6. Twig js jQuery Assetic Twig Symfony 2 Doctrine 2 MySQL PHPapp.wisembly.com/sflive
  7. 7. Backbone.js Underscore.js Twig js jQuery Assetic Twig Symfony 2 Doctrine 2 MySQL PHPapp.wisembly.com/sflive
  8. 8. Backbone.js Underscore.js Twig js jQuery H ! UC Assetic O M Twig TO Symfony 2 Doctrine 2 MySQL PHPapp.wisembly.com/sflive
  9. 9. Client Serverapp.wisembly.com/sflive
  10. 10. Client Twig REST Symfony 2 Server Doctrine 2 MySQL PHPapp.wisembly.com/sflive
  11. 11. Backbone.js Underscore.js Client jQuery HTML Twig REST Symfony 2 Server Doctrine 2 MySQL PHPapp.wisembly.com/sflive
  12. 12. Backbone.js Underscore.js Client jQuery ! HTML ING L L PO NG L O Twig REST Symfony 2 Server Doctrine 2 MySQL PHPapp.wisembly.com/sflive
  13. 13. Users want fast & smooth SaaS appsapp.wisembly.com/sflive
  14. 14. Users want fast & smooth SaaS apps Users want multiplateform SaaS appsapp.wisembly.com/sflive
  15. 15. Users want fast & smooth SaaS apps Users want multiplateform SaaS apps Users want dynamic & interactive SaaS appsapp.wisembly.com/sflive
  16. 16. Users want fast & smooth SaaS apps Users want multiplateform SaaS apps Users want dynamic & interactive SaaS apps You should do so!app.wisembly.com/sflive
  17. 17. Users want fast & smooth SaaS apps Users want multiplateform SaaS apps Users want dynamic & interactive SaaS apps W ? You shouldO so! do T H B Uapp.wisembly.com/sflive
  18. 18. app.wisembly.com/sflive
  19. 19. ?app.wisembly.com/sflive
  20. 20. E L L H ! N O ?app.wisembly.com/sflive
  21. 21. app.wisembly.com/sflive
  22. 22. Nowadaysapp.wisembly.com/sflive
  23. 23. app.wisembly.com/sflive
  24. 24. small / lightweight / stableapp.wisembly.com/sflive
  25. 25. small / lightweight / stable easy to learn, easy to extendapp.wisembly.com/sflive
  26. 26. small / lightweight / stable easy to learn, easy to extend great resources: layoutManager relationalapp.wisembly.com/sflive
  27. 27. Models Modelsapp.wisembly.com/sflive
  28. 28. Models Models Collections Repositoriesapp.wisembly.com/sflive
  29. 29. Models Models Collections Repositories Views Controllersapp.wisembly.com/sflive
  30. 30. Models Models Collections Repositories Views Controllers Templates Viewsapp.wisembly.com/sflive
  31. 31. Models Models Collections Repositories Views Controllers Templates Views Routing Routingapp.wisembly.com/sflive
  32. 32. Models Models Collections Repositories Views Controllers S H ViewsP U Templates + RE ST Routing Routingapp.wisembly.com/sflive
  33. 33. FOSJsRouting BazingaExposeTranslation JMSSerializer FOSRestBundleapp.wisembly.com/sflive
  34. 34. FOSJsRouting BazingaExposeTranslation JMSSerializer FOSRestBundleapp.wisembly.com/sflive
  35. 35. 1 - MAKE AN APIapp.wisembly.com/sflive
  36. 36. MUST READ http://fr.slideshare.net/nachomartin/symfony- javascript-combining-the-best-of-two-worldsapp.wisembly.com/sflive
  37. 37. ar tin nacm @ Books = new Backbone.collection(); Books.url = ‘/books’;app.wisembly.com/sflive
  38. 38. ar tin nacm @ Books = new Backbone.collection(); Books.url = ‘/books’; Books.fetch(); GET /booksapp.wisembly.com/sflive
  39. 39. ar tin nacm @ events: { ‘click .mybutton’:‘doStuffAndSave’ } doStuffAndSave: function() { var book = Books.get(3); book.stuff(); book.save(); }app.wisembly.com/sflive
  40. 40. ar tin nacm @ events: { ‘click .mybutton’:‘doStuffAndSave’ } doStuffAndSave: function() { var book = Books.get(3); book.stuff(); book.save(); } PUT /books/3app.wisembly.com/sflive
  41. 41. /** * @var integer $id * * @ORMColumn(name="id", type="integer") * @ORMId [ { * @ORMGeneratedValue(strategy="AUTO") “id”:1, */ “name”:”guillaume”, private $id; “phone”: “0611010011” /** ... * @var string $name * }, * @ORMColumn(name="name", type="string", {...}, length=50, nullable=true) ] */ private $name; /** * @var string $phone * * @ORMColumn(name="phone", type="string", length=20, nullable=true) */ private $phone; ...app.wisembly.com/sflive
  42. 42. II - MAKE A GOOD REST APIapp.wisembly.com/sflive
  43. 43. MUST READ 2 http://williamdurand.fr/2012/08/02/rest-apis- with-symfony2-the-right-wayapp.wisembly.com/sflive
  44. 44. JMSSerializer orapp.wisembly.com/sflive
  45. 45. JMSSerializer or class User implements UserInterface, EquatableInterface, ApiAbleInterface { }app.wisembly.com/sflive
  46. 46. JMSSerializer or class User implements UserInterface, EquatableInterface, ApiAbleInterface { public function toArray() { return [ id => $this->getId(), name => $this->getName(), email => $this->getEmail(), ]; } }app.wisembly.com/sflive
  47. 47. FOSRestBundle orapp.wisembly.com/sflive
  48. 48. FOSRestBundle or /** * @Route("{keyword}/quote/{id}", name="api3_quote_get", options={"expose"=true}) * @Method({"GET", "OPTIONS"}) */ public function getQuote(EventInterface $event, $id) { try { $quote = $this->get(api3.quote)->get($id); return $this->container->get(api3.response)->newSuccessResponse($quote- >toArray(), 200); } catch (NoResultException $e) { return $this->container->get(api3.response)->newErrorResponse(No quote found, ErrorCode::NO_QUOTE, 404); } }app.wisembly.com/sflive
  49. 49. FOSRestBundle or /** * @Route("{keyword}/quote/{id}", name="api3_quote_get", options={"expose"=true}) * @Method({"GET", "OPTIONS"}) */ public function getQuote(EventInterface $event, $id) { try { $quote = $this->get(api3.quote)->get($id); return $this->container->get(api3.response)->newSuccessResponse($quote- >toArray(), 200); } catch (NoResultException $e) { return $this->container->get(api3.response)->newErrorResponse(No quote found, ErrorCode::NO_QUOTE, 404); } }app.wisembly.com/sflive
  50. 50. FOSRestBundle or /** * @Route("{keyword}/quote/{id}", name="api3_quote_get", options={"expose"=true}) * @Method({"GET", "OPTIONS"}) */ public function getQuote(EventInterface $event, $id) { try { $quote = $this->get(api3.quote)->get($id); return $this->container->get(api3.response)->newSuccessResponse($quote- >toArray(), 200); } catch (NoResultException $e) { return $this->container->get(api3.response)->newErrorResponse(No quote found, ErrorCode::NO_QUOTE, 404); } }app.wisembly.com/sflive
  51. 51. FOSRestBundle or /** * @Route("{keyword}/quote/{id}", name="api3_quote_get", options={"expose"=true}) * @Method({"GET", "OPTIONS"}) */ public function getQuote(EventInterface $event, $id) { try { $quote = $this->get(api3.quote)->get($id); return $this->container->get(api3.response)->newSuccessResponse($quote- >toArray(), 200); } catch (NoResultException $e) { return $this->container->get(api3.response)->newErrorResponse(No quote found, ErrorCode::NO_QUOTE, 404); } }app.wisembly.com/sflive
  52. 52. FOSRestBundle or /** * @Route("{keyword}/quote/{id}", name="api3_quote_get", options={"expose"=true}) * @Method({"GET", "OPTIONS"}) */ public function getQuote(EventInterface $event, $id) { try { $quote = $this->get(api3.quote)->get($id); return $this->container->get(api3.response)->newSuccessResponse($quote- >toArray(), 200); } catch (NoResultException $e) { return $this->container->get(api3.response)->newErrorResponse(No quote found, ErrorCode::NO_QUOTE, 404); } }app.wisembly.com/sflive
  53. 53. FOSRestBundle or /** * @Route("{keyword}/quote/{id}", name="api3_quote_get", options={"expose"=true}) * @Method({"GET", "OPTIONS"}) */ public function getQuote(EventInterface $event, $id) { try { $quote = $this->get(api3.quote)->get($id); return $this->container->get(api3.response)->newSuccessResponse($quote- >toArray(), 200); } catch (NoResultException $e) { return $this->container->get(api3.response)->newErrorResponse(No quote found, ErrorCode::NO_QUOTE, 404); } }app.wisembly.com/sflive
  54. 54. FOSRestBundle or /** * @Route("{keyword}/quote/{id}", name="api3_quote_get", options={"expose"=true}) * @Method({"GET", "OPTIONS"}) */ public function getQuote(EventInterface $event, $id) { try { $quote = $this->get(api3.quote)->get($id); return $this->container->get(api3.response)->newSuccessResponse($quote- >toArray(), 200); } catch (NoResultException $e) { return $this->container->get(api3.response)->newErrorResponse(No quote found, ErrorCode::NO_QUOTE, 404); } }app.wisembly.com/sflive
  55. 55. Controller Entity Service API Service Entity EntityRepositoryapp.wisembly.com/sflive
  56. 56. Use Validator and Form ouac @c <?php // ... private function processForm(User $user) { $form = $this->createForm(new UserType(), $user); $form->bind($this->getRequest()); if ($form->isValid()) { $this->doYourStuff(); return $user; } // ... }app.wisembly.com/sflive
  57. 57. /** * @Route("event/{keyword}/poll/{id}", name="api3_poll_edit", requirements={"id" = "d+"}, options={"expose"=true}) * @Method({"POST", "PUT", "OPTIONS"}) */ public function editPollAction(EventInterface $event, Request $request, $id) { try { $poll = $this->get(api3.poll)->get($event, $id); $poll = $this->get(api3.poll)->edit($poll, $request); return $this->container->get(api3.response)->newSuccessResponse($poll- >toArray(), 201); } catch (NoResultException $e) { // ... } catch (AccessDeniedException $e) { // ... } catch (Exception $e) { // ... } }app.wisembly.com/sflive
  58. 58. /** * @Route("event/{keyword}/poll/{id}", name="api3_poll_edit", requirements={"id" = "d+"}, options={"expose"=true}) * @Method({"POST", "PUT", "OPTIONS"}) */ public function editPollAction(EventInterface $event, Request $request, $id) { try { $poll = $this->get(api3.poll)->get($event, $id); $poll = $this->get(api3.poll)->edit($poll, $request); return $this->container->get(api3.response)->newSuccessResponse($poll- >toArray(), 201); } catch (NoResultException $e) { // ... } catch (AccessDeniedException $e) { // ... } catch (Exception $e) { // ... } }app.wisembly.com/sflive
  59. 59. /** * @Route("event/{keyword}/poll/{id}", name="api3_poll_edit", requirements={"id" = "d+"}, options={"expose"=true}) * @Method({"POST", "PUT", "OPTIONS"}) */ public function editPollAction(EventInterface $event, Request $request, $id) { try { $poll = $this->get(api3.poll)->get($event, $id); $poll = $this->get(api3.poll)->edit($poll, $request); return $this->container->get(api3.response)->newSuccessResponse($poll- >toArray(), 201); } catch (NoResultException $e) { // ... } catch (AccessDeniedException $e) { // ... } catch (Exception $e) { // ... } }app.wisembly.com/sflive
  60. 60. /** * @Route("event/{keyword}/poll/{id}", name="api3_poll_edit", requirements={"id" = "d+"}, options={"expose"=true}) * @Method({"POST", "PUT", "OPTIONS"}) */ public function editPollAction(EventInterface $event, Request $request, $id) { try { $poll = $this->get(api3.poll)->get($event, $id); $poll = $this->get(api3.poll)->edit($poll, $request); return $this->container->get(api3.response)->newSuccessResponse($poll- >toArray(), 201); } catch (NoResultException $e) { // ... } catch (AccessDeniedException $e) { // ... } catch (Exception $e) { // ... } }app.wisembly.com/sflive
  61. 61. /** * @Route("event/{keyword}/poll/{id}", name="api3_poll_edit", requirements={"id" = "d+"}, options={"expose"=true}) * @Method({"POST", "PUT", "OPTIONS"}) */ public function editPollAction(EventInterface $event, Request $request, $id) { try { $poll = $this->get(api3.poll)->get($event, $id); $poll = $this->get(api3.poll)->edit($poll, $request); return $this->container->get(api3.response)->newSuccessResponse($poll- >toArray(), 201); } catch (NoResultException $e) { // ... } catch (AccessDeniedException $e) { // ... } catch (Exception $e) { // ... } }app.wisembly.com/sflive
  62. 62. app.wisembly.com/sflive
  63. 63. app.wisembly.com/sflive
  64. 64. FOSJsRouting BazingaExposeTranslation JMSSerializer FOSRestBundleapp.wisembly.com/sflive
  65. 65. ar tin nacm @ events: { ‘bookUpdated’:‘update’, ‘bookCreated’: ‘create’, ‘bookDeleted’:‘delete’, } update: function(websocketData) { doStuff(websocketData); }, create: function(websocketData) { doOtherStuff(websocketData); }, delete: function(websocketData) { stillDoOtherStuff(websocketData); }app.wisembly.com/sflive
  66. 66. ar tin nacm @ events: { ‘bookUpdated’:‘update’, ‘bookCreated’: ‘create’, ‘bookDeleted’:‘delete’, } update: function(websocketData) { doStuff(websocketData); }, create: function(websocketData) { doOtherStuff(websocketData); }, delete: function(websocketData) { stillDoOtherStuff(websocketData); } REAL TIME FULL EVENT BASEDapp.wisembly.com/sflive
  67. 67. websocketData? Who sends what? Which port, which protocol?app.wisembly.com/sflive
  68. 68. app.wisembly.com/sflive
  69. 69. FOSJsRouting BazingaExposeTranslation JMSSerializer FOSRestBundleapp.wisembly.com/sflive
  70. 70. Authenticate user against PUSH serverapp.wisembly.com/sflive
  71. 71. Authenticate user against PUSH server sessionToken domainapp.wisembly.com/sflive
  72. 72. Authenticate user against PUSH server sessionToken domain REST sessionToken domainapp.wisembly.com/sflive
  73. 73. Authenticate user against PUSH server sessionToken domain rights REST sessionToken domainapp.wisembly.com/sflive
  74. 74. Authenticate user against PUSH server Authenticated! rights REST sessionToken domainapp.wisembly.com/sflive
  75. 75. PUSH: The «Classic» way rightsapp.wisembly.com/sflive
  76. 76. PUSH: The «Classic» way REST sessionToken domain rightsapp.wisembly.com/sflive
  77. 77. PUSH: The «Classic» way REST sessionToken data domain rightsapp.wisembly.com/sflive
  78. 78. PUSH: The «Classic» way REST sessionToken data domain rightsapp.wisembly.com/sflive
  79. 79. PUSH: The «Classic» way websocketData REST sessionToken data domain rightsapp.wisembly.com/sflive
  80. 80. • Slow: HTTP ajax round-trip • !DRY: Double front processing (Ajax / Push) • Push server complexity: authorizationsapp.wisembly.com/sflive
  81. 81. PUSH: The «Wisembly» way websocketData REST sessionToken data domain rightsapp.wisembly.com/sflive
  82. 82. PUSH: The «Wisembly» way websocketData REST sessionToken domain websocketData secret rightsapp.wisembly.com/sflive
  83. 83. PUSH: The «Wisembly» way websocketData REST sessionToken domain websocketData websocketData secret rightsapp.wisembly.com/sflive
  84. 84. PUSH: The «Wisembly» way websocketData REST sessionToken data websocketData domain websocketData secret rightsapp.wisembly.com/sflive
  85. 85. Push «surprises»app.wisembly.com/sflive
  86. 86. Push «surprises» • Must find always opened portapp.wisembly.com/sflive
  87. 87. Push «surprises» • Must find always opened port • Websocket protocol must go through firewallsapp.wisembly.com/sflive
  88. 88. Push «surprises» • Must find always opened port • Websocket protocol must go through firewalls • Push may disconnect (very!) frequently and loose events (duh!)app.wisembly.com/sflive
  89. 89. app.wisembly.com/sflive
  90. 90. • 80 always opened, but websocket very often blocked -> FAIL -> goto 443 w/ httpsapp.wisembly.com/sflive
  91. 91. • 80 always opened, but websocket very often blocked -> FAIL -> goto 443 w/ https • Implement disconnection mechanism and lost events in case of socket.io «degraded» protocol (xhr polling, jsonp polling)app.wisembly.com/sflive
  92. 92. The «Wisembly» way hashN: { eventName, args }app.wisembly.com/sflive
  93. 93. The «Wisembly» way hashN: { eventName, args }app.wisembly.com/sflive
  94. 94. The «Wisembly» way hashN hashN hashN hash1: { eventName, args } hashN: { eventName, args } hash2: { eventName, args } ... hashN: { eventName, args } hashN: { eventName, args } hashN: { eventName, args }app.wisembly.com/sflive
  95. 95. The «Wisembly» way hashM hashM hashN hashN: { eventName, args } ...hashN+M: { eventName, args }app.wisembly.com/sflive
  96. 96. The «Wisembly» way hashM hashM hashN REST onReconect() since hashN hashN: { eventName, args } ...hashN+M: { eventName, args }app.wisembly.com/sflive
  97. 97. The «Wisembly» way hashM hashM hashN REST onReconect() since hashN hashN: { eventName, args } ...hashN+M: { eventName, args } hashN+1: { eventName, args } ... hashN+M: { eventName, args }app.wisembly.com/sflive
  98. 98. The «Wisembly» way hashM hashM hashM REST onReconect() since hashN hashN: { eventName, args } ...hashN+M: { eventName, args } hashN+1: { eventName, args } ... hashN+M: { eventName, args }app.wisembly.com/sflive
  99. 99. Great Ressources http://fr.slideshare.net/nachomartin/symfony-javascript- combining-the-best-of-two-worlds http://williamdurand.fr/2012/08/02/rest-apis-with- symfony2-the-right-wayapp.wisembly.com/sflive
  100. 100. @guillaumepotier http://wisembly.com/en/about#jobsapp.wisembly.com/sflive
  101. 101. Any Questions ?app.wisembly.com/sflive
  102. 102. app.wisembly.com/sflive
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×