KEMBAR78
Symfony & Javascript. Combining the best of two worlds | PDF
Symfony &
   JavaScript
Combining the best of two worlds




                   Nacho Martín
                    @nacmartin
Symfony &
   JavaScript
Combining the best of two worlds




                   Nacho Martín
                    @nacmartin
A bit of history
Client




Server
Client




Server
Client




Server
What’s that??
What’s that??

         It’s just a JavaScript
Client




Server
Client




Server
Client




Server
Client




Server
Client




Server
Why should I care?
Users like it
Users like it



You want to do it
Users expect it



You want to do it
Users expect it



You 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);
}
1
for(var i = 1; i <= 5; i++) {   2
  console.log(i);               3
}
                                4
                                5
for(var i = 1; i <= 5; i++) {
   setTimeout(function() {
      console.log(i);
   }, 100);
}
6
for(var i = 1; i <= 5; i++) {
   setTimeout(function() {      6
      console.log(i);           6
   }, 100);
}
                                6
                                6
for(var i = 1; i <= 5; i++) {
  (function() {
    var j = i;
    setTimeout(
        function() {
            console.log(j);
        }, 100);
  })();
}
for(var i = 1; i <= 5; i++) {
  (function() {                 1
    var j = i;
    setTimeout(
                                2
        function() {            3
            console.log(j);     4
        }, 100);
  })();                         5
}
Callback nesting
Callback nesting




• Events
Callback nesting




• Events
• Async.js
“this” gotcha
var o = {};
o.prop = {};

var o.f1 = function(){
    var that = this;

     this.prop.active = false;

     var activate = function(){
         that.prop.active = true;

     };

     activate();

};
“this” gotcha
var o = {};
o.prop = {};

var o.f1 = function(){
    var that = this;

     this.prop.active = false;

     var activate = function(){
         that.prop.active = true;

     };

     activate();

};
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 barrier
•Weird stuff inside
But, but...

•Can be ugly         •Huge community
•Tons of crappy code •Easy to get help
•Inconsistencies     •Low entry barrier
•Weird stuff inside •Is everywhere
http://www.flickr.com/photos/73935252@N00/181308667
The team needs discipline

                                 compromise readablity




http://www.flickr.com/photos/39865537@N03/4395203300
  http://www.flickr.com/photos/73935252@N00/181308667
Pick your battles




          http://www.flickr.com/photos/43322231@N07/5589147122
is the perfect
complement
is the perfect
complement
Client side JS
Level I




                             Text



          http://www.flickr.com/photos/lecates/307250887/
Assetic
FOSJsRouterBundle
PHP
/**
 * @Route ("/foo/{id}/bar", name="my_route_to_expose", options={"expose"=true})
 */
public function exposedAction($foo)




JS
Routing.generate('my_route_to_expose', { id: 10 });
// /foo/10/bar
Level II




  http://www.flickr.com/photos/49766155@N07/4945673508
                                 Text
Client




Server
Client




Server
Client




Server
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       • Routing
View



Model   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()




                GET /books
View


                Books=new Backbone.collection();
Model   Model   Books.url = ‘/books’;
                Books.fetch()




                GET /books
View        Books.on(‘reset’, this.render);




                Books=new Backbone.collection();
Model   Model   Books.url = ‘/books’;
                Books.fetch()




                GET /books
View        Books.on(‘reset’, this.render);




                Books=new Backbone.collection();
Model   Model   Books.url = ‘/books’;
                Books.fetch()




                GET /books
View        Books.on(‘reset’, this.render);




                Books=new Backbone.collection();
Model   Model   Books.url = ‘/books’;
                Books.fetch()




                GET /books
View



Model   Model
events: { ‘click .mybutton’: ‘doStuffAndSave’}
    View



Model   Model
events: { ‘click .mybutton’: ‘doStuffAndSave’}
    View



Model   Model
events: { ‘click .mybutton’: ‘doStuffAndSave’}
    View        doStuffAndSave: function() {
                  var book = Books.get(3);
                  book.stuff();
                  Books.get(3).save();
                }

Model   Model
events: { ‘click .mybutton’: ‘doStuffAndSave’}
    View        doStuffAndSave: function() {
                  var book = Books.get(3);
                  book.stuff();
                  Books.get(3).save();
                }

Model   Model
events: { ‘click .mybutton’: ‘doStuffAndSave’}
    View        doStuffAndSave: function() {
                  var book = Books.get(3);
                  book.stuff();
                  Books.get(3).save();
                }

Model   Model



                PUT /books/3
Build an API




        http://www.flickr.com/photos/kaptainkobold/3203311346/
FOSRestBundle

 /**
  * @View()
  * GET /users
  */
public function getUsersAction()
{
     return $this->getDoctrine()->getRepository('myBundle:User')->findAll();
}
[
           Response
    {“id”:1,
     “name”:”nacho”,
     “password”: “X$$%$X”,
     “email”:”nacho@limenius.com”,
     “profile”: {
             “id”:3,
             “phone”: “666666666”}
             }
    },
    {...},
]
JMSSerializer
MyBundleUser:
    exclusion_policy: ALL
    properties:
        id:
            expose: true
        name:
            expose: true
        email:
            expose: true
JMSSerializer
MyBundleUser:
    exclusion_policy: ALL
    properties:
        id:
            expose: true
        name:
            expose: true
        email:
            expose: true
    callback_methods:
        pre_serialize: serializeProfile
JMSSerializer

public 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-with-symfony2-the-right-
  way/
NelmioApiDocBundle
Twig.js



     Twig
Twig.js



 Backbone   Twig
Twig.js

{% javascripts "@MyBundle/Resources/views/tmpl.html.twig"
     filter="twig_js, ?yui_js" %}
    <script language="javascript" src="{{ asset_url }}">
    </script>
{% endjavascripts %}
Server side JS
Client




Server
Client




Server
Client




Server
Client




Server
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
♥
♥
♥
♥
Websockets



io.sockets.on('connection', function (socket) {
  socket.join('user1');
  socket.broadcast.to('user1').emit('Hi user 1');
});
Dealing with secrets




http://www.flickr.com/photos/45940879@N04/6277724736
http

MQ
The pusher way




secret     secret
The pusher way




         so
           ck
             et
             id


secret            secret
The pusher way



            id &
               e

                   so
      ck am


                     ck
    so l n




                       et
         et
        ne




                       id
     an
   ch




secret                      secret
ke
                y:s
                   ign
                       at
                          u




secret
         ch                 re
          an
             ne
         so l n
           ck am
              et    e
                 id &
                   so
                     ck
                       et
              id
                                 The pusher way




secret
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
Deploy
Deploy
Deploy
It’s just a JavaScript
Thanks
                   Nacho Martín
                    @nacmartin
                nacho@limenius.com




http://www.flickr.com/photos/95572727@N00/2380543038

Symfony & Javascript. Combining the best of two worlds