SlideShare a Scribd company logo
1 of 102
Download to read offline
Symfony2, Backbone.js
     & socket.io


    Symfony live Paris 2013

         @guillaumepotier
    guillaume@wisembly.com
app.wisembly.com/sflive


app.wisembly.com/sflive
2011, September

app.wisembly.com/sflive
MySQL

                          PHP



app.wisembly.com/sflive
Twig

                         Symfony 2

                         Doctrine 2

                          MySQL

                            PHP



app.wisembly.com/sflive
Twig js

                          jQuery

                          Assetic

                           Twig

                         Symfony 2

                         Doctrine 2

                          MySQL

                            PHP



app.wisembly.com/sflive
Backbone.js

                         Underscore.js

                            Twig js

                            jQuery

                            Assetic

                             Twig

                          Symfony 2

                          Doctrine 2

                            MySQL

                             PHP



app.wisembly.com/sflive
Backbone.js

                              Underscore.js

                                 Twig js

                                 jQuery
                                              H !
                                 UC
                                 Assetic


                              O M Twig

                         TO    Symfony 2

                               Doctrine 2

                                 MySQL

                                  PHP



app.wisembly.com/sflive
Client




  Server


app.wisembly.com/sflive
Client




                         Twig                REST
                                Symfony 2

  Server                        Doctrine 2
                                 MySQL

                                   PHP

app.wisembly.com/sflive
Backbone.js
                            Underscore.js
  Client                          jQuery
                                  HTML




                         Twig                REST
                                Symfony 2

  Server                        Doctrine 2
                                  MySQL

                                   PHP

app.wisembly.com/sflive
Backbone.js
                                  Underscore.js
  Client                                jQuery


                                                            !
                                        HTML


                                                        ING
                                     L                L
                                  PO
                               NG
                         L   O Twig                REST
                                      Symfony 2

  Server                              Doctrine 2
                                        MySQL

                                         PHP

app.wisembly.com/sflive
Users want fast & smooth SaaS apps




app.wisembly.com/sflive
Users want fast & smooth SaaS apps
                 Users want multiplateform SaaS apps




app.wisembly.com/sflive
Users want fast & smooth SaaS apps
              Users want multiplateform SaaS apps
           Users want dynamic & interactive SaaS apps




app.wisembly.com/sflive
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
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 U
app.wisembly.com/sflive
app.wisembly.com/sflive
?
app.wisembly.com/sflive
E L L
                         H !
                          N  O
                           ?
app.wisembly.com/sflive
app.wisembly.com/sflive
Nowadays


app.wisembly.com/sflive
app.wisembly.com/sflive
small / lightweight / stable




app.wisembly.com/sflive
small / lightweight / stable

                         easy to learn, easy to extend




app.wisembly.com/sflive
small / lightweight / stable

                         easy to learn, easy to extend

                               great resources:

                                 layoutManager
                                   relational



app.wisembly.com/sflive
Models   Models




app.wisembly.com/sflive
Models       Models

             Collections   Repositories




app.wisembly.com/sflive
Models       Models

             Collections   Repositories

                  Views    Controllers




app.wisembly.com/sflive
Models       Models

             Collections   Repositories

                  Views    Controllers

              Templates       Views



app.wisembly.com/sflive
Models       Models

             Collections   Repositories

                  Views    Controllers

              Templates       Views

                Routing      Routing
app.wisembly.com/sflive
Models           Models

             Collections       Repositories

                  Views        Controllers
                                              S H
                               ViewsP
                                     U
              Templates          +
                           RE ST
                Routing          Routing
app.wisembly.com/sflive
FOSJsRouting
 BazingaExposeTranslation
             JMSSerializer
          FOSRestBundle




app.wisembly.com/sflive
FOSJsRouting
 BazingaExposeTranslation
             JMSSerializer
          FOSRestBundle




app.wisembly.com/sflive
1 - MAKE AN API



app.wisembly.com/sflive
MUST READ


           http://fr.slideshare.net/nachomartin/symfony-
           javascript-combining-the-best-of-two-worlds




app.wisembly.com/sflive
ar tin
                                    nacm
                                   @


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




app.wisembly.com/sflive
ar tin
                                    nacm
                                   @


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




                           GET /books
app.wisembly.com/sflive
ar tin
                                    nacm
                                   @

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

                         doStuffAndSave: function() {
                           var book = Books.get(3);
                           book.stuff();
                           book.save();
                         }




app.wisembly.com/sflive
ar tin
                                    nacm
                                   @

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

                         doStuffAndSave: function() {
                           var book = Books.get(3);
                           book.stuff();
                           book.save();
                         }




                           PUT /books/3
app.wisembly.com/sflive
/**
                                         * @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
II - MAKE A GOOD
                    REST API


app.wisembly.com/sflive
MUST READ 2


           http://williamdurand.fr/2012/08/02/rest-apis-
           with-symfony2-the-right-way




app.wisembly.com/sflive
JMSSerializer

                              or




app.wisembly.com/sflive
JMSSerializer

                                           or
         class User implements UserInterface, EquatableInterface, ApiAbleInterface
         {




         }




app.wisembly.com/sflive
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
FOSRestBundle

                              or




app.wisembly.com/sflive
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
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
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
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
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
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
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
Controller


                    Entity Service       API Service


                         Entity       EntityRepository




app.wisembly.com/sflive
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
/**
         * @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
/**
         * @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
/**
         * @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
/**
         * @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
/**
         * @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
app.wisembly.com/sflive
app.wisembly.com/sflive
FOSJsRouting
 BazingaExposeTranslation
             JMSSerializer
          FOSRestBundle




app.wisembly.com/sflive
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
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 BASED
app.wisembly.com/sflive
websocketData?


                              Who sends what?


                         Which port, which protocol?




app.wisembly.com/sflive
app.wisembly.com/sflive
FOSJsRouting
 BazingaExposeTranslation
             JMSSerializer
          FOSRestBundle




app.wisembly.com/sflive
Authenticate user against
     PUSH server




app.wisembly.com/sflive
Authenticate user against
     PUSH server


                            sessionToken
                               domain




app.wisembly.com/sflive
Authenticate user against
     PUSH server


                                           sessionToken
                                              domain




                             REST
                            sessionToken
                               domain


app.wisembly.com/sflive
Authenticate user against
     PUSH server


                                           sessionToken
                                              domain




                             rights

                             REST
                            sessionToken
                               domain


app.wisembly.com/sflive
Authenticate user against
     PUSH server




                         Authenticated!

                              rights

                              REST
                             sessionToken
                                domain


app.wisembly.com/sflive
PUSH: The «Classic» way




                            rights

app.wisembly.com/sflive
PUSH: The «Classic» way




                     REST
                   sessionToken
                      domain




                                  rights

app.wisembly.com/sflive
PUSH: The «Classic» way




                     REST
                   sessionToken
                                  data
                      domain




                                         rights

app.wisembly.com/sflive
PUSH: The «Classic» way




                     REST
                   sessionToken
                                  data
                      domain




                                         rights

app.wisembly.com/sflive
PUSH: The «Classic» way




                                                  websocketData


                     REST
                   sessionToken
                                  data
                      domain




                                         rights

app.wisembly.com/sflive
• Slow: HTTP ajax round-trip
           • !DRY: Double front processing (Ajax / Push)
           • Push server complexity: authorizations


app.wisembly.com/sflive
PUSH: The «Wisembly» way




                                                  websocketData


                     REST
                   sessionToken
                                  data
                      domain




                                         rights

app.wisembly.com/sflive
PUSH: The «Wisembly» way




                                                           websocketData


                     REST
                   sessionToken
                      domain



                                  websocketData


                         secret
                                                  rights

app.wisembly.com/sflive
PUSH: The «Wisembly» way




                                                            websocketData


                     REST
                   sessionToken
                      domain            websocketData



                                  websocketData


                         secret
                                                   rights

app.wisembly.com/sflive
PUSH: The «Wisembly» way




                                                                   websocketData


                     REST
                   sessionToken
                                  data         websocketData
                      domain



                                         websocketData


                         secret
                                                          rights

app.wisembly.com/sflive
Push «surprises»




app.wisembly.com/sflive
Push «surprises»

      • Must find always opened port




app.wisembly.com/sflive
Push «surprises»

      • Must find always opened port
      • Websocket protocol must go through firewalls



app.wisembly.com/sflive
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
app.wisembly.com/sflive
• 80 always opened, but websocket very
               often blocked -> FAIL -> goto 443 w/ https




app.wisembly.com/sflive
• 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
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



                                                      hashN




     hash1: { eventName, args }                       hashN: { eventName, args }
     hash2: { eventName, args }
                ...
     hashN: { eventName, args }


                                  hashN: { eventName, args }




                                                                  hashN: { eventName, args }


app.wisembly.com/sflive
The «Wisembly» way

                                       hashM   hashM



                               hashN




 hashN: { eventName, args }
            ...
hashN+M: { eventName, args }




app.wisembly.com/sflive
The «Wisembly» way

                                                      hashM   hashM



                                              hashN
                                    REST
                               onReconect()
                                since hashN

 hashN: { eventName, args }
            ...
hashN+M: { eventName, args }




app.wisembly.com/sflive
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
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
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-way




app.wisembly.com/sflive
@guillaumepotier



   http://wisembly.com/en/about#jobs




app.wisembly.com/sflive
Any Questions ?




app.wisembly.com/sflive
app.wisembly.com/sflive

More Related Content

What's hot

Curso Symfony - Clase 4
Curso Symfony - Clase 4Curso Symfony - Clase 4
Curso Symfony - Clase 4Javier Eguiluz
 
Service approach for development REST API in Symfony2
Service approach for development REST API in Symfony2Service approach for development REST API in Symfony2
Service approach for development REST API in Symfony2Sumy PHP User Grpoup
 
Creating REST Applications with the Slim Micro-Framework by Vikram Vaswani
Creating REST Applications with the Slim Micro-Framework by Vikram VaswaniCreating REST Applications with the Slim Micro-Framework by Vikram Vaswani
Creating REST Applications with the Slim Micro-Framework by Vikram Vaswanivvaswani
 
Symfony tips and tricks
Symfony tips and tricksSymfony tips and tricks
Symfony tips and tricksJavier Eguiluz
 
Service approach for development Rest API in Symfony2
Service approach for development Rest API in Symfony2Service approach for development Rest API in Symfony2
Service approach for development Rest API in Symfony2Sumy PHP User Grpoup
 
REST in practice with Symfony2
REST in practice with Symfony2REST in practice with Symfony2
REST in practice with Symfony2Daniel Londero
 
Silex, the microframework
Silex, the microframeworkSilex, the microframework
Silex, the microframeworkInviqa
 
AngularJS with Slim PHP Micro Framework
AngularJS with Slim PHP Micro FrameworkAngularJS with Slim PHP Micro Framework
AngularJS with Slim PHP Micro FrameworkBackand Cohen
 
Hello World on Slim Framework 3.x
Hello World on Slim Framework 3.xHello World on Slim Framework 3.x
Hello World on Slim Framework 3.xRyan Szrama
 
Using Renderless Components in Vue.js during your software development.
Using Renderless Components in Vue.js during your software development.Using Renderless Components in Vue.js during your software development.
Using Renderless Components in Vue.js during your software development.tothepointIT
 
Creating the interfaces of the future with the APIs of today
Creating the interfaces of the future with the APIs of todayCreating the interfaces of the future with the APIs of today
Creating the interfaces of the future with the APIs of todaygerbille
 
How to learn to build your own PHP framework
How to learn to build your own PHP frameworkHow to learn to build your own PHP framework
How to learn to build your own PHP frameworkDinh Pham
 
Silex: From nothing to an API
Silex: From nothing to an APISilex: From nothing to an API
Silex: From nothing to an APIchrisdkemper
 
Curso Symfony - Clase 2
Curso Symfony - Clase 2Curso Symfony - Clase 2
Curso Symfony - Clase 2Javier Eguiluz
 
Wykorzystanie form request przy implementacji API w Laravelu
Wykorzystanie form request przy implementacji API w LaraveluWykorzystanie form request przy implementacji API w Laravelu
Wykorzystanie form request przy implementacji API w LaraveluLaravel Poland MeetUp
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasminePaulo Ragonha
 
20130528 solution linux_frousseau_nopain_webdev
20130528 solution linux_frousseau_nopain_webdev20130528 solution linux_frousseau_nopain_webdev
20130528 solution linux_frousseau_nopain_webdevFrank Rousseau
 
In The Trenches With Tomster, Upgrading Ember.js & Ember Data
In The Trenches With Tomster, Upgrading Ember.js & Ember DataIn The Trenches With Tomster, Upgrading Ember.js & Ember Data
In The Trenches With Tomster, Upgrading Ember.js & Ember DataStacy London
 

What's hot (20)

2021laravelconftwslides11
2021laravelconftwslides112021laravelconftwslides11
2021laravelconftwslides11
 
Curso Symfony - Clase 4
Curso Symfony - Clase 4Curso Symfony - Clase 4
Curso Symfony - Clase 4
 
Service approach for development REST API in Symfony2
Service approach for development REST API in Symfony2Service approach for development REST API in Symfony2
Service approach for development REST API in Symfony2
 
Creating REST Applications with the Slim Micro-Framework by Vikram Vaswani
Creating REST Applications with the Slim Micro-Framework by Vikram VaswaniCreating REST Applications with the Slim Micro-Framework by Vikram Vaswani
Creating REST Applications with the Slim Micro-Framework by Vikram Vaswani
 
Symfony tips and tricks
Symfony tips and tricksSymfony tips and tricks
Symfony tips and tricks
 
Service approach for development Rest API in Symfony2
Service approach for development Rest API in Symfony2Service approach for development Rest API in Symfony2
Service approach for development Rest API in Symfony2
 
REST in practice with Symfony2
REST in practice with Symfony2REST in practice with Symfony2
REST in practice with Symfony2
 
Silex, the microframework
Silex, the microframeworkSilex, the microframework
Silex, the microframework
 
AngularJS with Slim PHP Micro Framework
AngularJS with Slim PHP Micro FrameworkAngularJS with Slim PHP Micro Framework
AngularJS with Slim PHP Micro Framework
 
Hello World on Slim Framework 3.x
Hello World on Slim Framework 3.xHello World on Slim Framework 3.x
Hello World on Slim Framework 3.x
 
Using Renderless Components in Vue.js during your software development.
Using Renderless Components in Vue.js during your software development.Using Renderless Components in Vue.js during your software development.
Using Renderless Components in Vue.js during your software development.
 
Creating the interfaces of the future with the APIs of today
Creating the interfaces of the future with the APIs of todayCreating the interfaces of the future with the APIs of today
Creating the interfaces of the future with the APIs of today
 
How to learn to build your own PHP framework
How to learn to build your own PHP frameworkHow to learn to build your own PHP framework
How to learn to build your own PHP framework
 
Silex: From nothing to an API
Silex: From nothing to an APISilex: From nothing to an API
Silex: From nothing to an API
 
Curso Symfony - Clase 2
Curso Symfony - Clase 2Curso Symfony - Clase 2
Curso Symfony - Clase 2
 
Wykorzystanie form request przy implementacji API w Laravelu
Wykorzystanie form request przy implementacji API w LaraveluWykorzystanie form request przy implementacji API w Laravelu
Wykorzystanie form request przy implementacji API w Laravelu
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
 
Workshop 6: Designer tools
Workshop 6: Designer toolsWorkshop 6: Designer tools
Workshop 6: Designer tools
 
20130528 solution linux_frousseau_nopain_webdev
20130528 solution linux_frousseau_nopain_webdev20130528 solution linux_frousseau_nopain_webdev
20130528 solution linux_frousseau_nopain_webdev
 
In The Trenches With Tomster, Upgrading Ember.js & Ember Data
In The Trenches With Tomster, Upgrading Ember.js & Ember DataIn The Trenches With Tomster, Upgrading Ember.js & Ember Data
In The Trenches With Tomster, Upgrading Ember.js & Ember Data
 

Viewers also liked

How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony AppsKris Wallsmith
 
Symfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worldsSymfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worldsIgnacio Martín
 
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK MeetupScaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK MeetupKacper Gunia
 
Introduction to WAMP, a protocol enabling PUB/SUB and RPC over Websocket
Introduction to WAMP, a protocol enabling PUB/SUB and RPC over WebsocketIntroduction to WAMP, a protocol enabling PUB/SUB and RPC over Websocket
Introduction to WAMP, a protocol enabling PUB/SUB and RPC over Websocketsametmax
 
Behind the scenes of Real-Time Notifications
Behind the scenes of Real-Time NotificationsBehind the scenes of Real-Time Notifications
Behind the scenes of Real-Time NotificationsGuillermo Mansilla
 
Going crazy with Node.JS and CakePHP
Going crazy with Node.JS and CakePHPGoing crazy with Node.JS and CakePHP
Going crazy with Node.JS and CakePHPMariano Iglesias
 
The Wonderful World of Symfony Components
The Wonderful World of Symfony ComponentsThe Wonderful World of Symfony Components
The Wonderful World of Symfony ComponentsRyan Weaver
 
Git Flow: un processus de développement Agile
Git Flow: un processus de développement AgileGit Flow: un processus de développement Agile
Git Flow: un processus de développement AgileXavier Hausherr
 
Node Foundation Membership Overview 20160907
Node Foundation Membership Overview 20160907Node Foundation Membership Overview 20160907
Node Foundation Membership Overview 20160907NodejsFoundation
 

Viewers also liked (11)

How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony Apps
 
Symfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worldsSymfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worlds
 
Matters of State
Matters of StateMatters of State
Matters of State
 
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK MeetupScaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
 
Introduction to WAMP, a protocol enabling PUB/SUB and RPC over Websocket
Introduction to WAMP, a protocol enabling PUB/SUB and RPC over WebsocketIntroduction to WAMP, a protocol enabling PUB/SUB and RPC over Websocket
Introduction to WAMP, a protocol enabling PUB/SUB and RPC over Websocket
 
Behind the scenes of Real-Time Notifications
Behind the scenes of Real-Time NotificationsBehind the scenes of Real-Time Notifications
Behind the scenes of Real-Time Notifications
 
Going crazy with Node.JS and CakePHP
Going crazy with Node.JS and CakePHPGoing crazy with Node.JS and CakePHP
Going crazy with Node.JS and CakePHP
 
Building microservices
Building microservicesBuilding microservices
Building microservices
 
The Wonderful World of Symfony Components
The Wonderful World of Symfony ComponentsThe Wonderful World of Symfony Components
The Wonderful World of Symfony Components
 
Git Flow: un processus de développement Agile
Git Flow: un processus de développement AgileGit Flow: un processus de développement Agile
Git Flow: un processus de développement Agile
 
Node Foundation Membership Overview 20160907
Node Foundation Membership Overview 20160907Node Foundation Membership Overview 20160907
Node Foundation Membership Overview 20160907
 

Similar to Build Dynamic and Interactive SaaS Apps with Symfony, Backbone and Socket.io

In Pursuit of the Holy Grail: Building Isomorphic JavaScript Apps
In Pursuit of the Holy Grail: Building Isomorphic JavaScript AppsIn Pursuit of the Holy Grail: Building Isomorphic JavaScript Apps
In Pursuit of the Holy Grail: Building Isomorphic JavaScript AppsSpike Brehm
 
Beware the potholes
Beware the potholesBeware the potholes
Beware the potholesYan Cui
 
2012-04-18-shibuyarb-offline-mobile-app-has-great-potential
2012-04-18-shibuyarb-offline-mobile-app-has-great-potential2012-04-18-shibuyarb-offline-mobile-app-has-great-potential
2012-04-18-shibuyarb-offline-mobile-app-has-great-potentialKenichi Murahashi
 
Building a full-stack app with Golang and Google Cloud Platform in one week
Building a full-stack app with Golang and Google Cloud Platform in one weekBuilding a full-stack app with Golang and Google Cloud Platform in one week
Building a full-stack app with Golang and Google Cloud Platform in one weekDr. Felix Raab
 
Chisimba - introduction to practical demo
Chisimba - introduction to practical demoChisimba - introduction to practical demo
Chisimba - introduction to practical demoDerek Keats
 
Backend as a Service
Backend as a ServiceBackend as a Service
Backend as a Serviceapiomat
 
Beware the potholes on the road to serverless
Beware the potholes on the road to serverlessBeware the potholes on the road to serverless
Beware the potholes on the road to serverlessYan Cui
 
Wulin kungfu final
Wulin kungfu finalWulin kungfu final
Wulin kungfu finalJimmy Huang
 
OSGi Service Platform 4.2
OSGi Service Platform 4.2OSGi Service Platform 4.2
OSGi Service Platform 4.2Ilya Katsov
 
Libraries Frameworks And Cms
Libraries Frameworks And CmsLibraries Frameworks And Cms
Libraries Frameworks And CmsMark Casias
 
Volto: Plone Conference 2018
Volto: Plone Conference 2018Volto: Plone Conference 2018
Volto: Plone Conference 2018Rob Gietema
 
Symfony framework-An overview and usability for web development
Symfony framework-An overview and usability for web developmentSymfony framework-An overview and usability for web development
Symfony framework-An overview and usability for web developmentifour_bhavesh
 
Open innovation in software means Open Source (2011 remix)
Open innovation in software means Open Source (2011 remix)Open innovation in software means Open Source (2011 remix)
Open innovation in software means Open Source (2011 remix)Bertrand Delacretaz
 
jVoiD - the enterprise ecommerce Java by Schogini
jVoiD - the enterprise ecommerce Java by SchoginijVoiD - the enterprise ecommerce Java by Schogini
jVoiD - the enterprise ecommerce Java by SchoginiSchogini Systems Pvt Ltd
 
Mvvm is like born fraction
Mvvm is like born fractionMvvm is like born fraction
Mvvm is like born fractionKen Haneda
 
Learning Symfony2 by practice
Learning Symfony2 by practiceLearning Symfony2 by practice
Learning Symfony2 by practiceVytautas Beliunas
 
Wakanda: NoSQL for Model-Driven Web applications - NoSQL matters 2012
Wakanda: NoSQL for Model-Driven Web applications - NoSQL matters 2012Wakanda: NoSQL for Model-Driven Web applications - NoSQL matters 2012
Wakanda: NoSQL for Model-Driven Web applications - NoSQL matters 2012Alexandre Morgaut
 

Similar to Build Dynamic and Interactive SaaS Apps with Symfony, Backbone and Socket.io (20)

In Pursuit of the Holy Grail: Building Isomorphic JavaScript Apps
In Pursuit of the Holy Grail: Building Isomorphic JavaScript AppsIn Pursuit of the Holy Grail: Building Isomorphic JavaScript Apps
In Pursuit of the Holy Grail: Building Isomorphic JavaScript Apps
 
Beware the potholes
Beware the potholesBeware the potholes
Beware the potholes
 
2012-04-18-shibuyarb-offline-mobile-app-has-great-potential
2012-04-18-shibuyarb-offline-mobile-app-has-great-potential2012-04-18-shibuyarb-offline-mobile-app-has-great-potential
2012-04-18-shibuyarb-offline-mobile-app-has-great-potential
 
Building a full-stack app with Golang and Google Cloud Platform in one week
Building a full-stack app with Golang and Google Cloud Platform in one weekBuilding a full-stack app with Golang and Google Cloud Platform in one week
Building a full-stack app with Golang and Google Cloud Platform in one week
 
Chisimba - introduction to practical demo
Chisimba - introduction to practical demoChisimba - introduction to practical demo
Chisimba - introduction to practical demo
 
Backend as a Service
Backend as a ServiceBackend as a Service
Backend as a Service
 
Beware the potholes on the road to serverless
Beware the potholes on the road to serverlessBeware the potholes on the road to serverless
Beware the potholes on the road to serverless
 
Wulin kungfu final
Wulin kungfu finalWulin kungfu final
Wulin kungfu final
 
OSGi Service Platform 4.2
OSGi Service Platform 4.2OSGi Service Platform 4.2
OSGi Service Platform 4.2
 
Mashup Ecosystem
Mashup EcosystemMashup Ecosystem
Mashup Ecosystem
 
Libraries Frameworks And Cms
Libraries Frameworks And CmsLibraries Frameworks And Cms
Libraries Frameworks And Cms
 
Volto: Plone Conference 2018
Volto: Plone Conference 2018Volto: Plone Conference 2018
Volto: Plone Conference 2018
 
Build Programming Language Runtime with LLVM
Build Programming Language Runtime with LLVMBuild Programming Language Runtime with LLVM
Build Programming Language Runtime with LLVM
 
Symfony framework-An overview and usability for web development
Symfony framework-An overview and usability for web developmentSymfony framework-An overview and usability for web development
Symfony framework-An overview and usability for web development
 
Open innovation in software means Open Source (2011 remix)
Open innovation in software means Open Source (2011 remix)Open innovation in software means Open Source (2011 remix)
Open innovation in software means Open Source (2011 remix)
 
jVoiD - the enterprise ecommerce Java by Schogini
jVoiD - the enterprise ecommerce Java by SchoginijVoiD - the enterprise ecommerce Java by Schogini
jVoiD - the enterprise ecommerce Java by Schogini
 
Mvvm is like born fraction
Mvvm is like born fractionMvvm is like born fraction
Mvvm is like born fraction
 
Learning Symfony2 by practice
Learning Symfony2 by practiceLearning Symfony2 by practice
Learning Symfony2 by practice
 
Wakanda: NoSQL for Model-Driven Web applications - NoSQL matters 2012
Wakanda: NoSQL for Model-Driven Web applications - NoSQL matters 2012Wakanda: NoSQL for Model-Driven Web applications - NoSQL matters 2012
Wakanda: NoSQL for Model-Driven Web applications - NoSQL matters 2012
 
Isomorphic apps
Isomorphic appsIsomorphic apps
Isomorphic apps
 

Build Dynamic and Interactive SaaS Apps with Symfony, Backbone and Socket.io

  • 1. Symfony2, Backbone.js & socket.io Symfony live Paris 2013 @guillaumepotier guillaume@wisembly.com
  • 4. MySQL PHP app.wisembly.com/sflive
  • 5. Twig Symfony 2 Doctrine 2 MySQL PHP app.wisembly.com/sflive
  • 6. Twig js jQuery Assetic Twig Symfony 2 Doctrine 2 MySQL PHP app.wisembly.com/sflive
  • 7. Backbone.js Underscore.js Twig js jQuery Assetic Twig Symfony 2 Doctrine 2 MySQL PHP app.wisembly.com/sflive
  • 8. Backbone.js Underscore.js Twig js jQuery H ! UC Assetic O M Twig TO Symfony 2 Doctrine 2 MySQL PHP app.wisembly.com/sflive
  • 10. Client Twig REST Symfony 2 Server Doctrine 2 MySQL PHP app.wisembly.com/sflive
  • 11. Backbone.js Underscore.js Client jQuery HTML Twig REST Symfony 2 Server Doctrine 2 MySQL PHP app.wisembly.com/sflive
  • 12. Backbone.js Underscore.js Client jQuery ! HTML ING L L PO NG L O Twig REST Symfony 2 Server Doctrine 2 MySQL PHP app.wisembly.com/sflive
  • 13. Users want fast & smooth SaaS apps app.wisembly.com/sflive
  • 14. Users want fast & smooth SaaS apps Users want multiplateform SaaS apps app.wisembly.com/sflive
  • 15. Users want fast & smooth SaaS apps Users want multiplateform SaaS apps Users want dynamic & interactive SaaS apps app.wisembly.com/sflive
  • 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. 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 U app.wisembly.com/sflive
  • 20. E L L H ! N O ? app.wisembly.com/sflive
  • 24. small / lightweight / stable app.wisembly.com/sflive
  • 25. small / lightweight / stable easy to learn, easy to extend app.wisembly.com/sflive
  • 26. small / lightweight / stable easy to learn, easy to extend great resources: layoutManager relational app.wisembly.com/sflive
  • 27. Models Models app.wisembly.com/sflive
  • 28. Models Models Collections Repositories app.wisembly.com/sflive
  • 29. Models Models Collections Repositories Views Controllers app.wisembly.com/sflive
  • 30. Models Models Collections Repositories Views Controllers Templates Views app.wisembly.com/sflive
  • 31. Models Models Collections Repositories Views Controllers Templates Views Routing Routing app.wisembly.com/sflive
  • 32. Models Models Collections Repositories Views Controllers S H ViewsP U Templates + RE ST Routing Routing app.wisembly.com/sflive
  • 33. FOSJsRouting BazingaExposeTranslation JMSSerializer FOSRestBundle app.wisembly.com/sflive
  • 34. FOSJsRouting BazingaExposeTranslation JMSSerializer FOSRestBundle app.wisembly.com/sflive
  • 35. 1 - MAKE AN API app.wisembly.com/sflive
  • 36. MUST READ http://fr.slideshare.net/nachomartin/symfony- javascript-combining-the-best-of-two-worlds app.wisembly.com/sflive
  • 37. ar tin nacm @ Books = new Backbone.collection(); Books.url = ‘/books’; app.wisembly.com/sflive
  • 38. ar tin nacm @ Books = new Backbone.collection(); Books.url = ‘/books’; Books.fetch(); GET /books app.wisembly.com/sflive
  • 39. ar tin nacm @ events: { ‘click .mybutton’:‘doStuffAndSave’ } doStuffAndSave: function() { var book = Books.get(3); book.stuff(); book.save(); } app.wisembly.com/sflive
  • 40. ar tin nacm @ events: { ‘click .mybutton’:‘doStuffAndSave’ } doStuffAndSave: function() { var book = Books.get(3); book.stuff(); book.save(); } PUT /books/3 app.wisembly.com/sflive
  • 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. II - MAKE A GOOD REST API app.wisembly.com/sflive
  • 43. MUST READ 2 http://williamdurand.fr/2012/08/02/rest-apis- with-symfony2-the-right-way app.wisembly.com/sflive
  • 44. JMSSerializer or app.wisembly.com/sflive
  • 45. JMSSerializer or class User implements UserInterface, EquatableInterface, ApiAbleInterface { } app.wisembly.com/sflive
  • 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. FOSRestBundle or app.wisembly.com/sflive
  • 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. 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. 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. 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. 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. 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. 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. Controller Entity Service API Service Entity EntityRepository app.wisembly.com/sflive
  • 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. /** * @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. /** * @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. /** * @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. /** * @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. /** * @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
  • 64. FOSJsRouting BazingaExposeTranslation JMSSerializer FOSRestBundle app.wisembly.com/sflive
  • 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. 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 BASED app.wisembly.com/sflive
  • 67. websocketData? Who sends what? Which port, which protocol? app.wisembly.com/sflive
  • 69. FOSJsRouting BazingaExposeTranslation JMSSerializer FOSRestBundle app.wisembly.com/sflive
  • 70. Authenticate user against PUSH server app.wisembly.com/sflive
  • 71. Authenticate user against PUSH server sessionToken domain app.wisembly.com/sflive
  • 72. Authenticate user against PUSH server sessionToken domain REST sessionToken domain app.wisembly.com/sflive
  • 73. Authenticate user against PUSH server sessionToken domain rights REST sessionToken domain app.wisembly.com/sflive
  • 74. Authenticate user against PUSH server Authenticated! rights REST sessionToken domain app.wisembly.com/sflive
  • 75. PUSH: The «Classic» way rights app.wisembly.com/sflive
  • 76. PUSH: The «Classic» way REST sessionToken domain rights app.wisembly.com/sflive
  • 77. PUSH: The «Classic» way REST sessionToken data domain rights app.wisembly.com/sflive
  • 78. PUSH: The «Classic» way REST sessionToken data domain rights app.wisembly.com/sflive
  • 79. PUSH: The «Classic» way websocketData REST sessionToken data domain rights app.wisembly.com/sflive
  • 80. • Slow: HTTP ajax round-trip • !DRY: Double front processing (Ajax / Push) • Push server complexity: authorizations app.wisembly.com/sflive
  • 81. PUSH: The «Wisembly» way websocketData REST sessionToken data domain rights app.wisembly.com/sflive
  • 82. PUSH: The «Wisembly» way websocketData REST sessionToken domain websocketData secret rights app.wisembly.com/sflive
  • 83. PUSH: The «Wisembly» way websocketData REST sessionToken domain websocketData websocketData secret rights app.wisembly.com/sflive
  • 84. PUSH: The «Wisembly» way websocketData REST sessionToken data websocketData domain websocketData secret rights app.wisembly.com/sflive
  • 86. Push «surprises» • Must find always opened port app.wisembly.com/sflive
  • 87. Push «surprises» • Must find always opened port • Websocket protocol must go through firewalls app.wisembly.com/sflive
  • 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
  • 90. • 80 always opened, but websocket very often blocked -> FAIL -> goto 443 w/ https app.wisembly.com/sflive
  • 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. The «Wisembly» way hashN: { eventName, args } app.wisembly.com/sflive
  • 93. The «Wisembly» way hashN: { eventName, args } app.wisembly.com/sflive
  • 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. The «Wisembly» way hashM hashM hashN hashN: { eventName, args } ... hashN+M: { eventName, args } app.wisembly.com/sflive
  • 96. The «Wisembly» way hashM hashM hashN REST onReconect() since hashN hashN: { eventName, args } ... hashN+M: { eventName, args } app.wisembly.com/sflive
  • 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. 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. 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-way app.wisembly.com/sflive
  • 100. @guillaumepotier http://wisembly.com/en/about#jobs app.wisembly.com/sflive