Symfony &   JavaScriptCombining the best of two worlds                   Nacho Martín                    @nacmartin
Symfony &   JavaScriptCombining the best of two worlds                   Nacho Martín                    @nacmartin
A bit of history
ClientServer
ClientServer
ClientServer
What’s that??
What’s that??         It’s just a JavaScript
ClientServer
ClientServer
ClientServer
ClientServer
ClientServer
Why should I care?
Users like it
Users like itYou want to do it
Users expect itYou want to do it
Users expect itYou need to do it
It’s still just a JavaScript
But, but...JavaScript is HARD
Sequential
Sequential
Sequential
Sequential
Sequential
Sequential
Sequential
Asynchronous
Asynchronous
Asynchronous
Asynchronous       Call me back
Asynchronous
Asynchronous
Asynchronous         Done !
Asynchronous
for(var i = 1; i <= 5; i++) {  console.log(i);}
1for(var i = 1; i <= 5; i++) {   2  console.log(i);               3}                                4                     ...
for(var i = 1; i <= 5; i++) {   setTimeout(function() {      console.log(i);   }, 100);}
6for(var i = 1; i <= 5; i++) {   setTimeout(function() {      6      console.log(i);           6   }, 100);}              ...
for(var i = 1; i <= 5; i++) {  (function() {    var j = i;    setTimeout(        function() {            console.log(j);  ...
for(var i = 1; i <= 5; i++) {  (function() {                 1    var j = i;    setTimeout(                               ...
Callback nesting
Callback nesting• Events
Callback nesting• Events• Async.js
“this” gotchavar o = {};o.prop = {};var o.f1 = function(){    var that = this;     this.prop.active = false;     var activ...
“this” gotchavar o = {};o.prop = {};var o.f1 = function(){    var that = this;     this.prop.active = false;     var activ...
http://www.flickr.com/photos/bensonkua/3161323177/in/photostream/
Douglas Crockford
But, but...
But, but...•Can be ugly
But, but...•Can be ugly•Tons of crappy code
But, but...•Can be ugly•Tons of crappy code•Inconsistencies
But, but...•Can be ugly•Tons of crappy code•Inconsistencies•Weird stuff inside
But, but...•Can be ugly         •Huge community•Tons of crappy code•Inconsistencies•Weird stuff inside
But, but...•Can be ugly         •Huge community•Tons of crappy code •Easy to get help•Inconsistencies•Weird stuff inside
But, but...•Can be ugly         •Huge community•Tons of crappy code •Easy to get help•Inconsistencies     •Low entry barri...
But, but...•Can be ugly         •Huge community•Tons of crappy code •Easy to get help•Inconsistencies     •Low entry barri...
http://www.flickr.com/photos/73935252@N00/181308667
The team needs discipline                                 compromise readablityhttp://www.flickr.com/photos/39865537@N03/43...
Pick your battles          http://www.flickr.com/photos/43322231@N07/5589147122
is the perfectcomplement
is the perfectcomplement
Client side JS
Level I                             Text          http://www.flickr.com/photos/lecates/307250887/
Assetic
FOSJsRouterBundlePHP/** * @Route ("/foo/{id}/bar", name="my_route_to_expose", options={"expose"=true}) */public function e...
Level II  http://www.flickr.com/photos/49766155@N07/4945673508                                 Text
ClientServer
ClientServer
ClientServer
Then Symfony...?
Then Symfony...?Still does almost everything
•Small library•Stable for JS world•Active•Open Source•Popular
• Models        • Models• Collections   • Repositories• Views         • Controllers• Templates     • Views• Routing       ...
ViewModel   Model
View                Books=new Backbone.collection();Model   Model   Books.url = ‘/books’;                Books.fetch()
View                Books=new Backbone.collection();Model   Model   Books.url = ‘/books’;                Books.fetch()    ...
View                Books=new Backbone.collection();Model   Model   Books.url = ‘/books’;                Books.fetch()    ...
View        Books.on(‘reset’, this.render);                Books=new Backbone.collection();Model   Model   Books.url = ‘/b...
View        Books.on(‘reset’, this.render);                Books=new Backbone.collection();Model   Model   Books.url = ‘/b...
View        Books.on(‘reset’, this.render);                Books=new Backbone.collection();Model   Model   Books.url = ‘/b...
ViewModel   Model
events: { ‘click .mybutton’: ‘doStuffAndSave’}    ViewModel   Model
events: { ‘click .mybutton’: ‘doStuffAndSave’}    ViewModel   Model
events: { ‘click .mybutton’: ‘doStuffAndSave’}    View        doStuffAndSave: function() {                  var book = Boo...
events: { ‘click .mybutton’: ‘doStuffAndSave’}    View        doStuffAndSave: function() {                  var book = Boo...
events: { ‘click .mybutton’: ‘doStuffAndSave’}    View        doStuffAndSave: function() {                  var book = Boo...
Build an API        http://www.flickr.com/photos/kaptainkobold/3203311346/
FOSRestBundle /**  * @View()  * GET /users  */public function getUsersAction(){     return $this->getDoctrine()->getReposi...
[           Response    {“id”:1,     “name”:”nacho”,     “password”: “X$$%$X”,     “email”:”nacho@limenius.com”,     “prof...
JMSSerializerMyBundleUser:    exclusion_policy: ALL    properties:        id:            expose: true        name:        ...
JMSSerializerMyBundleUser:    exclusion_policy: ALL    properties:        id:            expose: true        name:        ...
JMSSerializerpublic function serializeProfile(){    $this->phone = $this->profile->getPhone();    $this->profile = null;}
Response[ {“id”:1,   “name”:”nacho”,   “email”:”nacho@limenius.com”,   “phone”: “666666666”   },   {...},]
Deserialize forms•SimpleThingsFormSerializeBundle•Symfony-cmf/CreateBundle•http://williamdurand.fr/2012/08/02/  rest-apis-...
NelmioApiDocBundle
Twig.js     Twig
Twig.js Backbone   Twig
Twig.js{% javascripts "@MyBundle/Resources/views/tmpl.html.twig"     filter="twig_js, ?yui_js" %}    <script language="jav...
Server side JS
ClientServer
ClientServer
ClientServer
ClientServer
What for
What for•Streaming data
What for•Streaming data•Soft realtime •Chats •Notifications
Challenges to face
Challenges to face•Organization of a big code base
Challenges to face•Organization of a big code base•General lower level of abstraction
Challenges to face•Organization of a big code base•General lower level of abstraction•Deployment •Serving static files
Challenges to face•Organization of a big code base•General lower level of abstraction•Deployment •Serving static files
Use case:Notifications
♥
♥
♥
♥
Websocketsio.sockets.on(connection, function (socket) {  socket.join(user1);  socket.broadcast.to(user1).emit(Hi user 1);});
Dealing with secretshttp://www.flickr.com/photos/45940879@N04/6277724736
httpMQ
The pusher waysecret     secret
The pusher way         so           ck             et             idsecret            secret
The pusher way            id &               e                   so      ck am                     ck    so l n           ...
ke                y:s                   ign                       at                          usecret         ch          ...
secret                               &The pusher way                             e                           am re        ...
Deploy
Deploy
Deploy
It’s just a JavaScript
Thanks                   Nacho Martín                    @nacmartin                nacho@limenius.comhttp://www.flickr.com/...
Symfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worlds
Próxima SlideShare
Cargando en…5
×

Symfony & Javascript. Combining the best of two worlds

18.196 visualizaciones

Publicado el

Publicado en: Tecnología
0 comentarios
32 recomendaciones
Estadísticas
Notas
  • Sé el primero en comentar

Sin descargas
Visualizaciones
Visualizaciones totales
18.196
En SlideShare
0
De insertados
0
Número de insertados
489
Acciones
Compartido
0
Descargas
230
Comentarios
0
Recomendaciones
32
Insertados 0
No insertados

No hay notas en la diapositiva.

Symfony & Javascript. Combining the best of two worlds

  1. 1. Symfony & JavaScriptCombining the best of two worlds Nacho Martín @nacmartin
  2. 2. Symfony & JavaScriptCombining the best of two worlds Nacho Martín @nacmartin
  3. 3. A bit of history
  4. 4. ClientServer
  5. 5. ClientServer
  6. 6. ClientServer
  7. 7. What’s that??
  8. 8. What’s that?? It’s just a JavaScript
  9. 9. ClientServer
  10. 10. ClientServer
  11. 11. ClientServer
  12. 12. ClientServer
  13. 13. ClientServer
  14. 14. Why should I care?
  15. 15. Users like it
  16. 16. Users like itYou want to do it
  17. 17. Users expect itYou want to do it
  18. 18. Users expect itYou need to do it
  19. 19. It’s still just a JavaScript
  20. 20. But, but...JavaScript is HARD
  21. 21. Sequential
  22. 22. Sequential
  23. 23. Sequential
  24. 24. Sequential
  25. 25. Sequential
  26. 26. Sequential
  27. 27. Sequential
  28. 28. Asynchronous
  29. 29. Asynchronous
  30. 30. Asynchronous
  31. 31. Asynchronous Call me back
  32. 32. Asynchronous
  33. 33. Asynchronous
  34. 34. Asynchronous Done !
  35. 35. Asynchronous
  36. 36. for(var i = 1; i <= 5; i++) { console.log(i);}
  37. 37. 1for(var i = 1; i <= 5; i++) { 2 console.log(i); 3} 4 5
  38. 38. for(var i = 1; i <= 5; i++) { setTimeout(function() { console.log(i); }, 100);}
  39. 39. 6for(var i = 1; i <= 5; i++) { setTimeout(function() { 6 console.log(i); 6 }, 100);} 6 6
  40. 40. for(var i = 1; i <= 5; i++) { (function() { var j = i; setTimeout( function() { console.log(j); }, 100); })();}
  41. 41. for(var i = 1; i <= 5; i++) { (function() { 1 var j = i; setTimeout( 2 function() { 3 console.log(j); 4 }, 100); })(); 5}
  42. 42. Callback nesting
  43. 43. Callback nesting• Events
  44. 44. Callback nesting• Events• Async.js
  45. 45. “this” gotchavar o = {};o.prop = {};var o.f1 = function(){ var that = this; this.prop.active = false; var activate = function(){ that.prop.active = true; }; activate();};
  46. 46. “this” gotchavar o = {};o.prop = {};var o.f1 = function(){ var that = this; this.prop.active = false; var activate = function(){ that.prop.active = true; }; activate();};
  47. 47. http://www.flickr.com/photos/bensonkua/3161323177/in/photostream/
  48. 48. Douglas Crockford
  49. 49. But, but...
  50. 50. But, but...•Can be ugly
  51. 51. But, but...•Can be ugly•Tons of crappy code
  52. 52. But, but...•Can be ugly•Tons of crappy code•Inconsistencies
  53. 53. But, but...•Can be ugly•Tons of crappy code•Inconsistencies•Weird stuff inside
  54. 54. But, but...•Can be ugly •Huge community•Tons of crappy code•Inconsistencies•Weird stuff inside
  55. 55. But, but...•Can be ugly •Huge community•Tons of crappy code •Easy to get help•Inconsistencies•Weird stuff inside
  56. 56. But, but...•Can be ugly •Huge community•Tons of crappy code •Easy to get help•Inconsistencies •Low entry barrier•Weird stuff inside
  57. 57. But, but...•Can be ugly •Huge community•Tons of crappy code •Easy to get help•Inconsistencies •Low entry barrier•Weird stuff inside •Is everywhere
  58. 58. http://www.flickr.com/photos/73935252@N00/181308667
  59. 59. The team needs discipline compromise readablityhttp://www.flickr.com/photos/39865537@N03/4395203300 http://www.flickr.com/photos/73935252@N00/181308667
  60. 60. Pick your battles http://www.flickr.com/photos/43322231@N07/5589147122
  61. 61. is the perfectcomplement
  62. 62. is the perfectcomplement
  63. 63. Client side JS
  64. 64. Level I Text http://www.flickr.com/photos/lecates/307250887/
  65. 65. Assetic
  66. 66. FOSJsRouterBundlePHP/** * @Route ("/foo/{id}/bar", name="my_route_to_expose", options={"expose"=true}) */public function exposedAction($foo)JSRouting.generate(my_route_to_expose, { id: 10 });// /foo/10/bar
  67. 67. Level II http://www.flickr.com/photos/49766155@N07/4945673508 Text
  68. 68. ClientServer
  69. 69. ClientServer
  70. 70. ClientServer
  71. 71. Then Symfony...?
  72. 72. Then Symfony...?Still does almost everything
  73. 73. •Small library•Stable for JS world•Active•Open Source•Popular
  74. 74. • Models • Models• Collections • Repositories• Views • Controllers• Templates • Views• Routing • Routing
  75. 75. ViewModel Model
  76. 76. View Books=new Backbone.collection();Model Model Books.url = ‘/books’; Books.fetch()
  77. 77. View Books=new Backbone.collection();Model Model Books.url = ‘/books’; Books.fetch() GET /books
  78. 78. View Books=new Backbone.collection();Model Model Books.url = ‘/books’; Books.fetch() GET /books
  79. 79. View Books.on(‘reset’, this.render); Books=new Backbone.collection();Model Model Books.url = ‘/books’; Books.fetch() GET /books
  80. 80. View Books.on(‘reset’, this.render); Books=new Backbone.collection();Model Model Books.url = ‘/books’; Books.fetch() GET /books
  81. 81. View Books.on(‘reset’, this.render); Books=new Backbone.collection();Model Model Books.url = ‘/books’; Books.fetch() GET /books
  82. 82. ViewModel Model
  83. 83. events: { ‘click .mybutton’: ‘doStuffAndSave’} ViewModel Model
  84. 84. events: { ‘click .mybutton’: ‘doStuffAndSave’} ViewModel Model
  85. 85. events: { ‘click .mybutton’: ‘doStuffAndSave’} View doStuffAndSave: function() { var book = Books.get(3); book.stuff(); Books.get(3).save(); }Model Model
  86. 86. events: { ‘click .mybutton’: ‘doStuffAndSave’} View doStuffAndSave: function() { var book = Books.get(3); book.stuff(); Books.get(3).save(); }Model Model
  87. 87. events: { ‘click .mybutton’: ‘doStuffAndSave’} View doStuffAndSave: function() { var book = Books.get(3); book.stuff(); Books.get(3).save(); }Model Model PUT /books/3
  88. 88. Build an API http://www.flickr.com/photos/kaptainkobold/3203311346/
  89. 89. FOSRestBundle /** * @View() * GET /users */public function getUsersAction(){ return $this->getDoctrine()->getRepository(myBundle:User)->findAll();}
  90. 90. [ Response {“id”:1, “name”:”nacho”, “password”: “X$$%$X”, “email”:”nacho@limenius.com”, “profile”: { “id”:3, “phone”: “666666666”} } }, {...},]
  91. 91. JMSSerializerMyBundleUser: exclusion_policy: ALL properties: id: expose: true name: expose: true email: expose: true
  92. 92. JMSSerializerMyBundleUser: exclusion_policy: ALL properties: id: expose: true name: expose: true email: expose: true callback_methods: pre_serialize: serializeProfile
  93. 93. JMSSerializerpublic function serializeProfile(){ $this->phone = $this->profile->getPhone(); $this->profile = null;}
  94. 94. Response[ {“id”:1, “name”:”nacho”, “email”:”nacho@limenius.com”, “phone”: “666666666” }, {...},]
  95. 95. Deserialize forms•SimpleThingsFormSerializeBundle•Symfony-cmf/CreateBundle•http://williamdurand.fr/2012/08/02/ rest-apis-with-symfony2-the-right- way/
  96. 96. NelmioApiDocBundle
  97. 97. Twig.js Twig
  98. 98. Twig.js Backbone Twig
  99. 99. Twig.js{% javascripts "@MyBundle/Resources/views/tmpl.html.twig" filter="twig_js, ?yui_js" %} <script language="javascript" src="{{ asset_url }}"> </script>{% endjavascripts %}
  100. 100. Server side JS
  101. 101. ClientServer
  102. 102. ClientServer
  103. 103. ClientServer
  104. 104. ClientServer
  105. 105. What for
  106. 106. What for•Streaming data
  107. 107. What for•Streaming data•Soft realtime •Chats •Notifications
  108. 108. Challenges to face
  109. 109. Challenges to face•Organization of a big code base
  110. 110. Challenges to face•Organization of a big code base•General lower level of abstraction
  111. 111. Challenges to face•Organization of a big code base•General lower level of abstraction•Deployment •Serving static files
  112. 112. Challenges to face•Organization of a big code base•General lower level of abstraction•Deployment •Serving static files
  113. 113. Use case:Notifications
  114. 114.
  115. 115.
  116. 116.
  117. 117.
  118. 118. Websocketsio.sockets.on(connection, function (socket) { socket.join(user1); socket.broadcast.to(user1).emit(Hi user 1);});
  119. 119. Dealing with secretshttp://www.flickr.com/photos/45940879@N04/6277724736
  120. 120. httpMQ
  121. 121. The pusher waysecret secret
  122. 122. The pusher way so ck et idsecret secret
  123. 123. The pusher way id & e so ck am ck so l n et et ne id an chsecret secret
  124. 124. ke y:s ign at usecret ch re an ne so l n ck am et e id & so ck et id The pusher waysecret
  125. 125. secret &The pusher way e am re l n tu ne na an sig ch y: ke id et ck so id & e et ck am so l n ne rean ch secret u at ign y:s ke
  126. 126. Deploy
  127. 127. Deploy
  128. 128. Deploy
  129. 129. It’s just a JavaScript
  130. 130. Thanks Nacho Martín @nacmartin nacho@limenius.comhttp://www.flickr.com/photos/95572727@N00/2380543038

×