SlideShare ist ein Scribd-Unternehmen logo
1 von 78
Downloaden Sie, um offline zu lesen
Exposer des services web
                                                   SOAP et REST




                                                                         RMLL - 6 juillet 2010




                       Sensio Labs Workshop    www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Qui suis-je ?

   ❖ Hugo HAMON (@hhamon)

   ❖ Responsable des formations chez Sensio Labs

   ❖ Coauteur et contributeur d’ouvrages

   ❖ Secrétaire Général de l’AFUP

   ❖ Webmaster du site Apprendre-PHP.com
   ❖ http://www.hugohamon.com

                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Introduction aux Web services




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Les services web



   ❖ Programmes destinés à échanger des données entre systèmes hétérogènes
   ❖ Basés sur des standards (SOAP) ou des styles d’architecture (REST)
   ❖ Fonctionnent en mode Client / Serveur (requête / réponse)
   ❖ Echange de données préformattées (XML, JSON, YAML, HTML...)
   ❖ Faible couplage grâce aux standards ouverts comme XML
   ❖ Faciles à mettre en oeuvre


                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Architecture REST




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
REST c’est quoi ?

   ❖ REpresentational State Transfert
   ❖ Concept inventé par Roy Fielding en 2000
   ❖ REST est un style d’architecture !
   ❖ REST s’appuie sur les concepts suivants :
        ❖ Le protocole HTTP (requête / réponse)
        ❖ La notion d’URI qui identifie chaque ressource
        ❖ Les méthodes HTTP (GET, POST, PUT, DELETE, HEAD)
        ❖ Les codes de statut (200, 201, 403, 404, 500...)
        ❖ Les formats ouverts (XML, JSON, HTML...)
   ❖ REST est simple à mettre en oeuvre

                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
La notion d’URI dans REST

   ❖ Chaque URI identifie une ressource

                                               http://api.domain.com/users/hugo


   ❖ Une URI ne contient pas de verbe !

   ❖ Une même URI peut être appelée avec différentes méthodes HTTP

     GET http://api.domain.com/users                                                               Récupère les utilisateurs


     POST http://api.domain.com/users                                                              Crée un nouvel utilisateur

                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Les méthodes HTTP

   ❖ GET, POST, PUT, DELETE et HEAD
   ❖ Identifient les actions réalisables sur la ressource

            GET http://api.domain.com/users                                                        Récupère les utilisateurs

            POST http://api.domain.com/users                                                       Crée un nouvel utilisateur

            PUT http://api.domain.com/users/hugo                                                          Modifie hugo

            DELETE http://api.domain.com/users/hugo                                                         Supprime hugo


   ❖ Opérations CRUD sur les ressources
                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Les codes HTTP de retour
   ❖ Indiquent l’état (succès ou échec) de l’opération effectuée

              Méthodes                                 En cas de succès                                 En cas d’échec

                                                       201 Created
                       POST                                                                         400 Bad Request
                                              Redirection vers l’URI de l’objet


                                                                                                    400 Bad Request
                       PUT                                           200 OK                         404 Not Found
                                                                                                    409 Conflict

                                                                                                    400 Bad Request
                  DELETE                                             200 OK                         404 Not Found
                                                                                                    410 Gone

                       GET                                           200 OK                         400 Bad Request
                                                                                                    404 Not Found

                       Sensio Labs Workshop    www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Symfony
                                               un framework RESTfull




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Introduction




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Présentation de symfony

   ❖ Framework PHP 5 MVC Open Source « full stack »
   ❖ Rapid Application Development
   ❖ Publié en 2005 sous licence MIT
   ❖ Bâti pour répondre à des besoins complexes
   ❖ « best practices » (design patterns, mvc, tests unitaires...)
   ❖ Maintenu par Sensio Labs jusqu’à fin 2012
   ❖ Documentation riche et Open Source (4 livres officiels)
   ❖ Communauté très active

                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Outillage de symfony



                        MVC                                                           Propel         CLI (CRUD)


          Tests Automatisés                                                                              ACL



                       Plugins                                                                          Cache


           I18N & L10N                                                                Doctrine      RESTful routing



                        Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Un routing RESTFull




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Routage de symfony

   ❖ Symfony découple les URLs du code (implémentation technique)

                                   /blog.php?section=symfony&article_id=18475


                                   /blog/2008-01-30/symfony-happy-new-year


     ❖ Optimisation pour les moteurs de recherche
     ❖ URIs faciles à copier / coller, mémoriser ou bookmarker
     ❖ Masque l’implémentation technique (php, python, ruby ?)
                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Contraindre les routes aux méthodes HTTP


 ❖ sfRequestRoute permet de contraindre les URIs aux méthodes HTTP
 ❖ Une même URI peut être atteinte avec des méthodes HTTP différentes


                              user_edit:
                                class: sfRequestRoute
                                url:   /api/users/:username
                                param: { module: user, action: update }
                                requirements: { sf_method: put }




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Contraindre les routes aux méthodes HTTP



                                               $ php symfony app:routes api




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Contraindre les routes aux méthodes HTTP


 ❖ Symfony simule les requêtes PUT et DELETE depuis un navigateur
 ❖ Les formulaires embarquent un champ caché « sf_method »

<form action="/api_dev.php/api/user/hugo" method="post">
  <input type="hidden" value="put" name="sf_method"/>
  <input type="hidden" id="rmll_user_id" value="2" name="rmll_user[id]"/>
  <input type="hidden" id="rmll_user__csrf_token"
value="94c132e7c771411590124aea52bb9d4f" name="rmll_user[_csrf_token]"/>
  <!-- ... -->
</form>




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Contraindre les routes aux méthodes HTTP

                $params = array(
                   'method' => 'delete',
                   'confirm' => 'Etes-vous sûr de vouloir supprimer cet objet ?'
                );

                echo link_to('supprimer', 'user_delete', $object, $params);




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Contraindre les routes aux méthodes HTTP

                $params = array(
                   'method' => 'delete',
                   'confirm' => 'Etes-vous sûr de vouloir supprimer cet objet ?'
                );

                echo link_to('supprimer', 'user_delete', $object, $params);



        <li class="sf_admin_action_delete"><a href="/api_dev.php/api/user/hugo"
        onclick="if (confirm('Are you sure?')) { var f = document.createElement
        ('form'); f.style.display = 'none'; this.parentNode.appendChild(f);
        f.method = 'post'; f.action = this.href;var m = document.createElement
        ('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name',
        'sf_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var m
        = document.createElement('input'); m.setAttribute('type', 'hidden');
        m.setAttribute('name', '_csrf_token'); m.setAttribute('value',
        'f0271a52cca50e62df7deb1568f80489'); f.appendChild(m);f.submit
        (); };return false;">Supprimer</a></li>

                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Les routes d’objets



                               user_edit

                                       Route                                                                  Objet Doctrine RmllUser

                                                                                            Base de données

   user_edit:
     class: sfDoctrineRoute
     url:   /api/users/:username
     param: { module: user, action: update }
     options: { model: RmllUser, column: username, type: object }
     requirements: { sf_method: put }



                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Les routes d’objets
       public function executeUpdate(sfWebRequest $request)
       {
         $user = $this->getRoute()->getObject();

             $form = new RmllUserForm($user, array(), false);
             $form->bind($request->getParameter('rmll_user'));

             $status = 400;
             if ($form->isValid())
             {
               $form->save();
               $status = 200;
             }

             $this->getResponse()->setStatusCode($status);
             return sfView::NONE;
       }

                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Les collections de routes d’objets


                  ❖ sfDoctrineRouteCollection ou sfPropelRouteCollection
                  ❖ Actions CRUD sur un objet de modèle

                              user
                           user_new
                          user_create
                            user_edit
                          user_update
                          user_delete
                           user_show

                       Collection de routes                                                        Base de données   Objet Doctrine RmllUser

                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Les collections de routes d’objets


                       user:
                         class: sfDoctrineRouteCollection
                         options:
                           model:                RmllUser
                           module:               user
                           prefix_path:          /api/users
                           column:               username
                           with_wildcard_routes: true
                           actions: [list, create, update, delete, show]




                        Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Les collections de routes d’objets




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Support des formats de sortie




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Support des formats de sortie

 ❖ Par défaut, symfony supporte le format HTML
 ❖ Le paramètre « sf_format » définit le format de sortie
 ❖ Symfony se charge d’envoyer les bons en-têtes en fonction de l’extension
                               user:
                                 class: sfDoctrineRouteCollection
                                 options:
                                   model:                RmllUser
                                   module:               user
                                   prefix_path:          /api/users
                                   column:               username
                                   with_wildcard_routes: true
                                   actions: [list, create, update, delete, show]
                                 requirements: { sf_format: (?:html|xml|json) }


                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
http://api.domain.com/users/hugo.xml




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
http://api.domain.com/users/hugo.xml



                                                             executeShow($request)




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
http://api.domain.com/users/hugo.xml



                                                             executeShow($request)



       showSuccess.php                                     showSuccess.xml.php                     showSuccess.json.php




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
http://api.domain.com/users/hugo.xml



                                                             executeShow($request)



       showSuccess.php                                     showSuccess.xml.php                     showSuccess.json.php




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
<h1><?php echo $user ?></h1>
  <table>                                                                                          showSuccess.php
    <tbody>
      <tr>
        <td>Username</td>
        <td><?php echo $user->getUsername() ?></td>
      </tr>
      <tr>
        <td>Password</td>
        <td><?php echo $user->getPassword() ?></td>
      </tr>
      <tr>
        <td>First name</td>
        <td><?php echo $user->getFirstName() ?></td>
      </tr>
      <tr>
        <td>Last name</td>
        <td><?php echo $user->getLastName() ?></td>
      </tr>
      <tr>
        <td>Birthdate</td>
        <td><?php echo $user->getBirthdate() ?></td>
      </tr>
    </tbody>
  </table>


                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
<?php echo '<?xml version="1.0" encoding="UTF-8" ?>'."n" ?>
           <user>
             <username><?php echo $user->getUsername() ?></username>
             <firstName><?php echo $user->getFirstName() ?></firstName>
             <lastName><?php echo $user->getLastName() ?></lastName>
             <birthdate><?php echo $user->getBirthdate() ?></birthdate>
           </user>
                                                                                                   showSuccess.xml.php


                                   showSuccess.json.php
    {
         "username":                      <?php        echo         json_encode($user->getUsername()) ?>,
         "firstName":                     <?php        echo         json_encode($user->getFirstName(ESC_RAW)) ?>,
         "lastName":                      <?php        echo         json_encode($user->getLastName(ESC_RAW)) ?>,
         "birthdate":                     <?php        echo         json_encode($user->getBirthdate()) ."n" ?>
    }



                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Sortie HTML




                                                                                                   Sortie XML




                                                                                                   Sortie JSON



                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Cache des résultats




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Cache des résultats
   ❖ Symfony dispose nativement d’un cache HTML des pages
        ❖ Chaque sortie générée peut être mise en cache sur le serveur
        ❖ La durée de vie du cache de chaque page est configurable
        ❖ Le cache est par défaut stocké sur le système de fichier (sfFileCache)

   ❖ Symfony offre la possibilité de choisir où stocker le cache :
        ❖ Fichiers (sfFileCache)
        ❖ SQLite (sfSQLiteCache)
        ❖ XCache (sfXCacheCache)
        ❖ MemCache (sfMemCacheCache)
        ❖ APC... (sfAPCCache)
                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Cache des résultats


                                     ❖ apps/api/modules/user/config/cache.yml


                                                         show:
                                                           enabled:                                true
                                                           with_layout:                            true
                                                           lifetime:                               3600




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Avant la mise en cache


                                                                                                   336 ms




                                                  Après la mise en cache


                                                                                                   50 ms



                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Tests Fonctionnels
                                                            de l’API




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Simuler des requêtes GET
                   include(dirname(__FILE__).'/../../bootstrap/functional.php');

                   $browser = new RmllTestFunctional(new sfBrowser());
                   $browser->loadFixtures();

                   $browser->
                     get('/api/users/hhamon.xml')->

                       with('request')->begin()->
                         isFormat('xml')->
                         isParameter('module', 'user')->
                         isParameter('action', 'show')->
                       end()->

                       with('response')->begin()->
                         isStatusCode(200)->
                         isValid()->
                       end();


                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Simuler des requêtes GET
                   include(dirname(__FILE__).'/../../bootstrap/functional.php');

                   $browser = new RmllTestFunctional(new sfBrowser());
                   $browser->loadFixtures();

                   $browser->
                     get('/api/users/hhamon.xml')->                                                GET sur le fichier XML
                       with('request')->begin()->
                         isFormat('xml')->
                         isParameter('module', 'user')->
                         isParameter('action', 'show')->
                       end()->

                       with('response')->begin()->
                         isStatusCode(200)->
                         isValid()->
                       end();


                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Simuler des requêtes GET
                   include(dirname(__FILE__).'/../../bootstrap/functional.php');

                   $browser = new RmllTestFunctional(new sfBrowser());
                   $browser->loadFixtures();

                   $browser->
                     get('/api/users/hhamon.xml')->                                                 GET sur le fichier XML
                       with('request')->begin()->
                         isFormat('xml')->
                         isParameter('module', 'user')->                                           Vérification de la requête
                         isParameter('action', 'show')->
                       end()->

                       with('response')->begin()->
                         isStatusCode(200)->
                         isValid()->
                       end();


                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Simuler des requêtes GET
                   include(dirname(__FILE__).'/../../bootstrap/functional.php');

                   $browser = new RmllTestFunctional(new sfBrowser());
                   $browser->loadFixtures();

                   $browser->
                     get('/api/users/hhamon.xml')->                                                 GET sur le fichier XML
                       with('request')->begin()->
                         isFormat('xml')->
                         isParameter('module', 'user')->                                           Vérification de la requête
                         isParameter('action', 'show')->
                       end()->

                       with('response')->begin()->
                         isStatusCode(200)->                                                       Vérification de la réponse
                         isValid()->
                       end();


                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Simuler des requêtes GET




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
$user = array(
             'username' => 'pmartin',
             'password' => 'something',
             'first_name' => 'Paul',
             'last_name' => 'Martin'
          );

          $user = getUser(array('birthdate' => ''));
          $browser->
            post('/api/users', array('rmll_user' => $user))->
            with('response')->isStatusCode(400);

          $browser->
            post('/api/users', array('rmll_user' => getUser()))->
            with('response')->begin()->
              isStatusCode(201)->
              isRedirected()->
            end()->
            followRedirect()



                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
$user = array(
             'username' => 'pmartin',
             'password' => 'something',
             'first_name' => 'Paul',
             'last_name' => 'Martin'
          );

          $user = getUser(array('birthdate' => ''));
          $browser->
            post('/api/users', array('rmll_user' => $user))->
            with('response')->isStatusCode(400);

          $browser->
            post('/api/users', array('rmll_user' => getUser()))->
            with('response')->begin()->
              isStatusCode(201)->
              isRedirected()->
            end()->
            followRedirect()



                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
$user = array(
             'username' => 'pmartin',
             'password' => 'something',
             'first_name' => 'Paul',                                                               Test de la création avec des
             'last_name' => 'Martin'                                                                 paramètres manquants
          );

          $user = getUser(array('birthdate' => ''));
          $browser->
            post('/api/users', array('rmll_user' => $user))->
            with('response')->isStatusCode(400);

          $browser->
            post('/api/users', array('rmll_user' => getUser()))->
            with('response')->begin()->
              isStatusCode(201)->
              isRedirected()->
            end()->
            followRedirect()



                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
$user = array(
             'username' => 'pmartin',
             'password' => 'something',
             'first_name' => 'Paul',                                                               Test de la création avec des
             'last_name' => 'Martin'                                                                 paramètres manquants
          );

          $user = getUser(array('birthdate' => ''));
          $browser->
            post('/api/users', array('rmll_user' => $user))->
            with('response')->isStatusCode(400);

          $browser->
            post('/api/users', array('rmll_user' => getUser()))->
            with('response')->begin()->
              isStatusCode(201)->
              isRedirected()->
            end()->
            followRedirect()



                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
$user = array(
             'username' => 'pmartin',
             'password' => 'something',
             'first_name' => 'Paul',                                                               Test de la création avec des
             'last_name' => 'Martin'                                                                 paramètres manquants
          );

          $user = getUser(array('birthdate' => ''));
          $browser->
            post('/api/users', array('rmll_user' => $user))->
            with('response')->isStatusCode(400);

          $browser->
            post('/api/users', array('rmll_user' => getUser()))->
            with('response')->begin()->
              isStatusCode(201)->
              isRedirected()->
            end()->
            followRedirect()                    Test de la création avec                                                       des
                                                                                                          paramètres valides
                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Simuler des requêtes POST




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Simuler des requêtes PUT
   $user = getUser(array('first_name' => 'Toto'));
   $browser->
     call('/api/users/pmartin', 'put', array('rmll_user' => $user))->
     with('response')->isStatusCode(200)
   ;




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Simuler des requêtes PUT
   $user = getUser(array('first_name' => 'Toto'));
   $browser->
     call('/api/users/pmartin', 'put', array('rmll_user' => $user))->
     with('response')->isStatusCode(200)
   ;




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Simuler des requêtes DELETE


                                 $browser->
                                   call('/api/users/pmartin', 'delete')->
                                   with('response')->isStatusCode(200);




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Simuler des requêtes DELETE


                                 $browser->
                                   call('/api/users/pmartin', 'delete')->
                                   with('response')->isStatusCode(200);




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Architecture SOAP




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Introduction à SOAP




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Qu’est-ce que SOAP ?

  ❖ « Simple Object Access Protocol »
  ❖ SOAP est un protocole standard (http://www.w3.org/TR/soap/)

  ❖ Appel de procédure à distance reposant sur un standard XML
  ❖ SOAP permet d’invoquer des méthodes sur un objet distant
  ❖ La réponse est servie au client SOAP sous forme d’une réponse SOAP XML
  ❖ Transport des requêtes et réponses SOAP avec le protocole HTTP
  ❖ Les requêtes et réponses SOAP sont des chaînes XML
  ❖ Les données sont traitées sur le serveur puis converties en XML

                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Avantages et Inconvénients



         ❖ Avantages :                                                                             ❖ Inconvénients :
              ✤ Standard éprouvé                                                                    ✤ Lourd et lent
              ✤ Indépendant de la plateforme                                                        ✤ Verbosité du XML
              ✤ Indépendant du langage                                                              ✤ Difficile à tester et à cacher
              ✤ Extensible



                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Fonctionnement de SOAP


                                              http://domain.com/service?wsdl




                                                     http://domain.com/service

                 SOAP Client

                                                                                                   SOAP Serveur




                         $service = new FooService();
                         $response = $s->calledMethod($param1, $param2);




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Exposer des services SOAP
                                            avec symfony et Zend




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
class ProjectConfiguration extends sfProjectConfiguration
     {
       static protected $zendLoaded = false;

         public function setup()
         {
           $this->enablePlugins('sfDoctrinePlugin');
           self::registerZend();
         }

         static public function registerZend()
         {
           if (self::$zendLoaded) {
             return;
           }

              set_include_path(
                 sfConfig::get('sf_lib_dir').'/vendor'.PATH_SEPARATOR.get_include_path()
              );
              require_once sfConfig::get('sf_lib_dir').'/vendor/Zend/Loader/Autoloader.php';
              Zend_Loader_Autoloader::getInstance();
              self::$zendLoaded = true;
         }
     }


                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
class ProjectConfiguration extends sfProjectConfiguration
     {
       static protected $zendLoaded = false;
                                                                                                   Framework Zend dans
         public function setup()
                                                                                                      lib/vendor/Zend
         {
           $this->enablePlugins('sfDoctrinePlugin');
           self::registerZend();
         }

         static public function registerZend()
         {
           if (self::$zendLoaded) {
             return;
           }

              set_include_path(
                 sfConfig::get('sf_lib_dir').'/vendor'.PATH_SEPARATOR.get_include_path()
              );
              require_once sfConfig::get('sf_lib_dir').'/vendor/Zend/Loader/Autoloader.php';
              Zend_Loader_Autoloader::getInstance();
              self::$zendLoaded = true;
         }
     }


                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
class ProjectConfiguration extends sfProjectConfiguration
     {
       static protected $zendLoaded = false;
                                                                                                   Framework Zend dans
         public function setup()
                                                                                                      lib/vendor/Zend
         {
           $this->enablePlugins('sfDoctrinePlugin');
           self::registerZend();
         }

         static public function registerZend()
                                                                                                       Initialisation de
         {
           if (self::$zendLoaded) {                                                                l’autoloader de Zend
             return;
           }

              set_include_path(
                 sfConfig::get('sf_lib_dir').'/vendor'.PATH_SEPARATOR.get_include_path()
              );
              require_once sfConfig::get('sf_lib_dir').'/vendor/Zend/Loader/Autoloader.php';
              Zend_Loader_Autoloader::getInstance();
              self::$zendLoaded = true;
         }
     }


                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Création d’un module et d’une route

  ❖ Création d’un nouveau module converter

                               $ php symfony generate:module api converter




  ❖ Création d’une nouvelle route converter_service dans routing.yml

                           converter_service:
                             url:        /converter/service
                             param:      { module: converter, action: index }




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
class TemperatureConverterService
    {
      /**
        * Converts a Celsius temperature into a Fahrenheit temperature.
        *
        * @param float $value The value to convert
        * @return float
        */
      public function convertCelsiusToFahrenheit($value)
      {
          return 1.8 * $value + 32;
      }

         /**
           * Converts a Fahrenheit temperature into a Celsius temperature.
           *
           * @param float $value The value to convert
           * @return float
           */
         public function convertFahrenheitToCelsius($value)
         {
             return (5/9) * $value - 160/9;
         }
    }                                                                                              PHPDoc importante

                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Dévoiler le WSDL

      public function executeWsdl(sfWebRequest $request)
      {
        try
        {
          $wsdl = new Zend_Soap_AutoDiscover();
          $wsdl->setClass('TemperatureConverterService');
          $wsdl->handle();
        }
        catch (Exception $e)
        {
          $this->logMessage($e->getMessage());
        }

            return sfView::NONE;
      }


                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Dévoiler le WSDL

      public function executeWsdl(sfWebRequest $request)
      {
        try
        {
          $wsdl = new Zend_Soap_AutoDiscover();
          $wsdl->setClass('TemperatureConverterService');
          $wsdl->handle();
        }
        catch (Exception $e)
        {
          $this->logMessage($e->getMessage());
        }

            return sfView::NONE;                                                                    Zend génère le WSDL par
      }                                                                                            introspection de la PHPDoc
                                                                                                      de la classe du service

                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
http://api.domain.com/converter/service?wsdl




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Implémenter la passerelle du service

 public function executeIndex(sfWebRequest $request)
 {
   $this->forwardIf(null !== $request->getParameter('wsdl'), 'converter', 'wsdl');

      try
      {
        $wsdl   = $this->generateUrl('converter_service', array(), true).'?wsdl';
        $server = new Zend_Soap_Server($wsdl);
        $server->setClass('TemperatureConverterService');
        $server->setReturnResponse(true);
        $this->renderText($server->handle());
      }
      catch (Exception $e)
      {
        $this->logMessage($e->getMessage());
      }

      return sfView::NONE;
 }



                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Consommer le service SOAP




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Consommer le service SOAP

    try
    {
      $client = new Zend_Soap_Client(
         'http://api.domain.com/converter/service?wsdl'
      );

         $celsiusToFahrenheit = $client->convertCelsiusToFahrenheit(30.50);
         $fahrenheitToCelsius = $client->convertFahrenheitToCelsius(72.30);
    }
    catch (SoapFault $e)
    {
      exit($e->getMessage());
    }

    echo $celsiusToFahrenheit;
    echo $fahrenheitToCelsius;




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Tester le service SOAP




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Tester le service SOAP


  ❖ Tester un service SOAP avec PHP est assez compliqué !
       ❖ La requête et la réponse doivent être testées
       ❖ Les réponses doivent être simulées (mock)

  ❖ Zend_Soap a l’avantage d’être déjà testé par Zend
  ❖ Le fonctionnement de symfony est déjà testé également
  ❖ A tester unitairement : la classe TemperatureConverterService

                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Tests unitaires du service

     // test/unit/service/TemperatureConverterServiceTest.php
     require dirname(__FILE__).'/../../bootstrap/unit.php';

     $t = new lime_test(3);
     $service = new TemperatureConverterService();

     $t->diag('->convertCelsiusToFahrenheit()');

     $result = $service->convertCelsiusToFahrenheit(0);
     $t->is($result, 32, '->convertCelsiusToFahrenheit() returns 32');

     $result = $service->convertCelsiusToFahrenheit(1);
     $t->is($result, 33.8, '->convertCelsiusToFahrenheit() returns 33.8');

     $result = $service->convertCelsiusToFahrenheit(10);
     $t->is($result, 50, '->convertCelsiusToFahrenheit() returns 50');



                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Tests unitaires du service


                $ php symfony test:unit TemperatureConverterService




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Tests unitaires du service
    // test/unit/service/TemperatureConverterServiceTest.php
    require dirname(__FILE__).'/../../bootstrap/unit.php';

    $t = new lime_test(6);
    $service = new TemperatureConverterService();

    // ...

    $t->diag('->convertFahrenheitToCelsius()');

    $result = $service->convertFahrenheitToCelsius(0);
    $t->is($result, -160/9, '->convertFahrenheitToCelsius() returns -160/9');

    $result = $service->convertFahrenheitToCelsius(33.8);
    $t->is($result, 1, '->convertFahrenheitToCelsius() returns 1');

    $result = $service->convertFahrenheitToCelsius(50);
    $t->is($result, 10, '->convertFahrenheitToCelsius() returns 10');


                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Tests unitaires du service


                $ php symfony test:unit TemperatureConverterService




                       Sensio Labs Workshop   www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010
Questions ?




                                                    Sensio Labs recrute !

                                              hugo.hamon@sensio.com


                       Sensio Labs Workshop    www.symfony-project.org   trainings.sensiolabs.com

mardi 6 juillet 2010

Weitere ähnliche Inhalte

Was ist angesagt?

Spring Framework
Spring Framework  Spring Framework
Spring Framework tola99
 
Présentation de RMI Java
Présentation de RMI JavaPrésentation de RMI Java
Présentation de RMI JavaZakaria Bouazza
 
ASP.NET Core MVC + Web API with Overview
ASP.NET Core MVC + Web API with OverviewASP.NET Core MVC + Web API with Overview
ASP.NET Core MVC + Web API with OverviewShahed Chowdhuri
 
Jdbc architecture and driver types ppt
Jdbc architecture and driver types pptJdbc architecture and driver types ppt
Jdbc architecture and driver types pptkamal kotecha
 
ASP.NET Web API
ASP.NET Web APIASP.NET Web API
ASP.NET Web APIhabib_786
 
MVC ppt presentation
MVC ppt presentationMVC ppt presentation
MVC ppt presentationBhavin Shah
 
Hibernate architecture
Hibernate architectureHibernate architecture
Hibernate architectureAnurag
 
Introduction à spring boot
Introduction à spring bootIntroduction à spring boot
Introduction à spring bootAntoine Rey
 
Installation of java and program execution
Installation of java and program executionInstallation of java and program execution
Installation of java and program executionRakhee Chhibber
 
Formation JAVA/J2EE
Formation JAVA/J2EEFormation JAVA/J2EE
Formation JAVA/J2EEInes Ouaz
 
Entreprise Java Beans (EJB)
Entreprise Java Beans (EJB)Entreprise Java Beans (EJB)
Entreprise Java Beans (EJB)Heithem Abbes
 
Rest api standards and best practices
Rest api standards and best practicesRest api standards and best practices
Rest api standards and best practicesAnkita Mahajan
 

Was ist angesagt? (20)

Presentation Spring
Presentation SpringPresentation Spring
Presentation Spring
 
Spring Framework
Spring Framework  Spring Framework
Spring Framework
 
Présentation de RMI Java
Présentation de RMI JavaPrésentation de RMI Java
Présentation de RMI Java
 
Curso de Java: Threads
Curso de Java: ThreadsCurso de Java: Threads
Curso de Java: Threads
 
ASP.NET Core MVC + Web API with Overview
ASP.NET Core MVC + Web API with OverviewASP.NET Core MVC + Web API with Overview
ASP.NET Core MVC + Web API with Overview
 
Jdbc architecture and driver types ppt
Jdbc architecture and driver types pptJdbc architecture and driver types ppt
Jdbc architecture and driver types ppt
 
ASP.NET Web API
ASP.NET Web APIASP.NET Web API
ASP.NET Web API
 
MVC ppt presentation
MVC ppt presentationMVC ppt presentation
MVC ppt presentation
 
Introduction to Spring Boot
Introduction to Spring BootIntroduction to Spring Boot
Introduction to Spring Boot
 
Hibernate architecture
Hibernate architectureHibernate architecture
Hibernate architecture
 
Introduction à spring boot
Introduction à spring bootIntroduction à spring boot
Introduction à spring boot
 
Installation of java and program execution
Installation of java and program executionInstallation of java and program execution
Installation of java and program execution
 
Spring MVC Framework
Spring MVC FrameworkSpring MVC Framework
Spring MVC Framework
 
Nouveautés de java 8
Nouveautés de java 8Nouveautés de java 8
Nouveautés de java 8
 
RESTful Web Services
RESTful Web ServicesRESTful Web Services
RESTful Web Services
 
Formation JAVA/J2EE
Formation JAVA/J2EEFormation JAVA/J2EE
Formation JAVA/J2EE
 
Java Collections Tutorials
Java Collections TutorialsJava Collections Tutorials
Java Collections Tutorials
 
Entreprise Java Beans (EJB)
Entreprise Java Beans (EJB)Entreprise Java Beans (EJB)
Entreprise Java Beans (EJB)
 
Rest api standards and best practices
Rest api standards and best practicesRest api standards and best practices
Rest api standards and best practices
 
Traitement distribue en BIg Data - KAFKA Broker and Kafka Streams
Traitement distribue en BIg Data - KAFKA Broker and Kafka StreamsTraitement distribue en BIg Data - KAFKA Broker and Kafka Streams
Traitement distribue en BIg Data - KAFKA Broker and Kafka Streams
 

Andere mochten auch

Les web services
Les web servicesLes web services
Les web servicesdihiaselma
 
RESTful avec symfony 1 et Symfony2
RESTful avec symfony 1 et Symfony2RESTful avec symfony 1 et Symfony2
RESTful avec symfony 1 et Symfony2Xavier Lacot
 
Working with oro crm entities
Working with oro crm entitiesWorking with oro crm entities
Working with oro crm entitiesOro Inc.
 
Boostez vos-developpements-symfony-avec-phpedit
Boostez vos-developpements-symfony-avec-phpeditBoostez vos-developpements-symfony-avec-phpedit
Boostez vos-developpements-symfony-avec-phpeditauto entrepreneur
 
La Console Symfony
La Console Symfony La Console Symfony
La Console Symfony Imad ZAIRIG
 
OroPlatform and OroCRM from a developer's perspective
OroPlatform and OroCRM from a developer's perspectiveOroPlatform and OroCRM from a developer's perspective
OroPlatform and OroCRM from a developer's perspectiveYevhen Shyshkin
 
Conference drupal 8 au Forum PHP 2013 à Paris
Conference drupal 8 au Forum PHP 2013 à ParisConference drupal 8 au Forum PHP 2013 à Paris
Conference drupal 8 au Forum PHP 2013 à ParisChipway
 
Symfony live Paris 2014 - Symfony2 sur Azure
Symfony live Paris 2014 - Symfony2 sur AzureSymfony live Paris 2014 - Symfony2 sur Azure
Symfony live Paris 2014 - Symfony2 sur AzureStéphane ESCANDELL
 
symfony : Un Framework Open-Source pour les Professionnels
symfony : Un Framework Open-Source pour les Professionnelssymfony : Un Framework Open-Source pour les Professionnels
symfony : Un Framework Open-Source pour les ProfessionnelsFabien Potencier
 
Drupal 8 + Symfony 2 = une équipe gagnante
Drupal 8 + Symfony 2 = une équipe gagnanteDrupal 8 + Symfony 2 = une équipe gagnante
Drupal 8 + Symfony 2 = une équipe gagnanteVanessa David
 
symfony: Un Framework Open-Source pour les Entreprises (Solutions Linux 2008)
symfony: Un Framework Open-Source pour les Entreprises (Solutions Linux 2008)symfony: Un Framework Open-Source pour les Entreprises (Solutions Linux 2008)
symfony: Un Framework Open-Source pour les Entreprises (Solutions Linux 2008)Fabien Potencier
 
Symfony et Sonata Project chez Canal+
Symfony et Sonata Project chez Canal+ Symfony et Sonata Project chez Canal+
Symfony et Sonata Project chez Canal+ ekino
 
Symfony2: 30 astuces et bonnes pratiques
Symfony2: 30 astuces et bonnes pratiquesSymfony2: 30 astuces et bonnes pratiques
Symfony2: 30 astuces et bonnes pratiquesNoel GUILBERT
 
Design patterns avec Symfony
Design patterns avec SymfonyDesign patterns avec Symfony
Design patterns avec SymfonyMohammed Rhamnia
 
Introduction aux web services
Introduction aux web servicesIntroduction aux web services
Introduction aux web servicesmohammed addoumi
 
Tendances Futures du Web - GTI780 & MTI780 - ETS - A08
Tendances Futures du Web - GTI780 & MTI780 - ETS - A08Tendances Futures du Web - GTI780 & MTI780 - ETS - A08
Tendances Futures du Web - GTI780 & MTI780 - ETS - A08Claude Coulombe
 
Utilisation de services Web sécurisés en Java en environnement Open Source
Utilisation de services Web sécurisés en Java en environnement Open SourceUtilisation de services Web sécurisés en Java en environnement Open Source
Utilisation de services Web sécurisés en Java en environnement Open Sourceguest3be047
 

Andere mochten auch (20)

Les web services
Les web servicesLes web services
Les web services
 
RESTful avec symfony 1 et Symfony2
RESTful avec symfony 1 et Symfony2RESTful avec symfony 1 et Symfony2
RESTful avec symfony 1 et Symfony2
 
Working with oro crm entities
Working with oro crm entitiesWorking with oro crm entities
Working with oro crm entities
 
Boostez vos-developpements-symfony-avec-phpedit
Boostez vos-developpements-symfony-avec-phpeditBoostez vos-developpements-symfony-avec-phpedit
Boostez vos-developpements-symfony-avec-phpedit
 
La Console Symfony
La Console Symfony La Console Symfony
La Console Symfony
 
OroPlatform and OroCRM from a developer's perspective
OroPlatform and OroCRM from a developer's perspectiveOroPlatform and OroCRM from a developer's perspective
OroPlatform and OroCRM from a developer's perspective
 
Presentation symfony
Presentation symfonyPresentation symfony
Presentation symfony
 
Drupal 8
Drupal 8Drupal 8
Drupal 8
 
Conference drupal 8 au Forum PHP 2013 à Paris
Conference drupal 8 au Forum PHP 2013 à ParisConference drupal 8 au Forum PHP 2013 à Paris
Conference drupal 8 au Forum PHP 2013 à Paris
 
Symfony live Paris 2014 - Symfony2 sur Azure
Symfony live Paris 2014 - Symfony2 sur AzureSymfony live Paris 2014 - Symfony2 sur Azure
Symfony live Paris 2014 - Symfony2 sur Azure
 
symfony : Un Framework Open-Source pour les Professionnels
symfony : Un Framework Open-Source pour les Professionnelssymfony : Un Framework Open-Source pour les Professionnels
symfony : Un Framework Open-Source pour les Professionnels
 
Symfonytn
SymfonytnSymfonytn
Symfonytn
 
Drupal 8 + Symfony 2 = une équipe gagnante
Drupal 8 + Symfony 2 = une équipe gagnanteDrupal 8 + Symfony 2 = une équipe gagnante
Drupal 8 + Symfony 2 = une équipe gagnante
 
symfony: Un Framework Open-Source pour les Entreprises (Solutions Linux 2008)
symfony: Un Framework Open-Source pour les Entreprises (Solutions Linux 2008)symfony: Un Framework Open-Source pour les Entreprises (Solutions Linux 2008)
symfony: Un Framework Open-Source pour les Entreprises (Solutions Linux 2008)
 
Symfony et Sonata Project chez Canal+
Symfony et Sonata Project chez Canal+ Symfony et Sonata Project chez Canal+
Symfony et Sonata Project chez Canal+
 
Symfony2: 30 astuces et bonnes pratiques
Symfony2: 30 astuces et bonnes pratiquesSymfony2: 30 astuces et bonnes pratiques
Symfony2: 30 astuces et bonnes pratiques
 
Design patterns avec Symfony
Design patterns avec SymfonyDesign patterns avec Symfony
Design patterns avec Symfony
 
Introduction aux web services
Introduction aux web servicesIntroduction aux web services
Introduction aux web services
 
Tendances Futures du Web - GTI780 & MTI780 - ETS - A08
Tendances Futures du Web - GTI780 & MTI780 - ETS - A08Tendances Futures du Web - GTI780 & MTI780 - ETS - A08
Tendances Futures du Web - GTI780 & MTI780 - ETS - A08
 
Utilisation de services Web sécurisés en Java en environnement Open Source
Utilisation de services Web sécurisés en Java en environnement Open SourceUtilisation de services Web sécurisés en Java en environnement Open Source
Utilisation de services Web sécurisés en Java en environnement Open Source
 

Ähnlich wie Exposer des services web SOAP et REST avec symfony 1.4 et Zend Framework

[fr] Introduction et Live-code Backbone.js à DevoxxFR 2013
[fr] Introduction et Live-code Backbone.js à DevoxxFR 2013[fr] Introduction et Live-code Backbone.js à DevoxxFR 2013
[fr] Introduction et Live-code Backbone.js à DevoxxFR 2013Sylvain Zimmer
 
Mieux Développer en PHP avec Symfony
Mieux Développer en PHP avec SymfonyMieux Développer en PHP avec Symfony
Mieux Développer en PHP avec SymfonyHugo Hamon
 
L'avenir du web au prisme de la ressource
L'avenir du web au prisme de la ressourceL'avenir du web au prisme de la ressource
L'avenir du web au prisme de la ressourcePascale Laurent
 
Zoo Presentation SIG La Lettre 2011
Zoo Presentation SIG La Lettre 2011Zoo Presentation SIG La Lettre 2011
Zoo Presentation SIG La Lettre 2011djayzen
 
Annexe1 éTude Comparative Sur Les Moteurs De Recherche
Annexe1   éTude Comparative Sur Les Moteurs De RechercheAnnexe1   éTude Comparative Sur Les Moteurs De Recherche
Annexe1 éTude Comparative Sur Les Moteurs De RechercheMohamed Ben Bouzid
 
TechDays 2010 : SharePoint Workspace
TechDays 2010 : SharePoint WorkspaceTechDays 2010 : SharePoint Workspace
TechDays 2010 : SharePoint WorkspaceFabrice BARBIN
 
Migration d'Exalead vers Solr - IFCE et France Labs - Search Day 2014
Migration d'Exalead vers Solr - IFCE et France Labs - Search Day 2014Migration d'Exalead vers Solr - IFCE et France Labs - Search Day 2014
Migration d'Exalead vers Solr - IFCE et France Labs - Search Day 2014francelabs
 
Diaporama du sfPot Lillois du 20 mars 2014
Diaporama du sfPot Lillois du 20 mars 2014Diaporama du sfPot Lillois du 20 mars 2014
Diaporama du sfPot Lillois du 20 mars 2014Les-Tilleuls.coop
 

Ähnlich wie Exposer des services web SOAP et REST avec symfony 1.4 et Zend Framework (10)

[fr] Introduction et Live-code Backbone.js à DevoxxFR 2013
[fr] Introduction et Live-code Backbone.js à DevoxxFR 2013[fr] Introduction et Live-code Backbone.js à DevoxxFR 2013
[fr] Introduction et Live-code Backbone.js à DevoxxFR 2013
 
Mieux Développer en PHP avec Symfony
Mieux Développer en PHP avec SymfonyMieux Développer en PHP avec Symfony
Mieux Développer en PHP avec Symfony
 
L'avenir du web au prisme de la ressource
L'avenir du web au prisme de la ressourceL'avenir du web au prisme de la ressource
L'avenir du web au prisme de la ressource
 
Zoo Presentation SIG La Lettre 2011
Zoo Presentation SIG La Lettre 2011Zoo Presentation SIG La Lettre 2011
Zoo Presentation SIG La Lettre 2011
 
Tutoriel : "Gestion d’ontologies"
Tutoriel : "Gestion d’ontologies"Tutoriel : "Gestion d’ontologies"
Tutoriel : "Gestion d’ontologies"
 
Annexe1 éTude Comparative Sur Les Moteurs De Recherche
Annexe1   éTude Comparative Sur Les Moteurs De RechercheAnnexe1   éTude Comparative Sur Les Moteurs De Recherche
Annexe1 éTude Comparative Sur Les Moteurs De Recherche
 
TechDays 2010 : SharePoint Workspace
TechDays 2010 : SharePoint WorkspaceTechDays 2010 : SharePoint Workspace
TechDays 2010 : SharePoint Workspace
 
cours6.pdf
cours6.pdfcours6.pdf
cours6.pdf
 
Migration d'Exalead vers Solr - IFCE et France Labs - Search Day 2014
Migration d'Exalead vers Solr - IFCE et France Labs - Search Day 2014Migration d'Exalead vers Solr - IFCE et France Labs - Search Day 2014
Migration d'Exalead vers Solr - IFCE et France Labs - Search Day 2014
 
Diaporama du sfPot Lillois du 20 mars 2014
Diaporama du sfPot Lillois du 20 mars 2014Diaporama du sfPot Lillois du 20 mars 2014
Diaporama du sfPot Lillois du 20 mars 2014
 

Mehr von Hugo Hamon

Design Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleHugo Hamon
 
Monitor the quality of your Symfony projects
Monitor the quality of your Symfony projectsMonitor the quality of your Symfony projects
Monitor the quality of your Symfony projectsHugo Hamon
 
Database Design Patterns
Database Design PatternsDatabase Design Patterns
Database Design PatternsHugo Hamon
 
Silex meets SOAP & REST
Silex meets SOAP & RESTSilex meets SOAP & REST
Silex meets SOAP & RESTHugo Hamon
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistenceHugo Hamon
 
Intégration Continue PHP avec Jenkins CI
Intégration Continue PHP avec Jenkins CIIntégration Continue PHP avec Jenkins CI
Intégration Continue PHP avec Jenkins CIHugo Hamon
 
Symfony2 - extending the console component
Symfony2 - extending the console componentSymfony2 - extending the console component
Symfony2 - extending the console componentHugo Hamon
 
Développeurs, cachez-moi ça ! (Paris Web 2011)
Développeurs, cachez-moi ça ! (Paris Web 2011)Développeurs, cachez-moi ça ! (Paris Web 2011)
Développeurs, cachez-moi ça ! (Paris Web 2011)Hugo Hamon
 
Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2Hugo Hamon
 
Symfony2 - Un Framework PHP 5 Performant
Symfony2 - Un Framework PHP 5 PerformantSymfony2 - Un Framework PHP 5 Performant
Symfony2 - Un Framework PHP 5 PerformantHugo Hamon
 
Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2Hugo Hamon
 
Intégration continue des projets PHP avec Jenkins
Intégration continue des projets PHP avec JenkinsIntégration continue des projets PHP avec Jenkins
Intégration continue des projets PHP avec JenkinsHugo Hamon
 
Symfony2 en pièces détachées
Symfony2 en pièces détachéesSymfony2 en pièces détachées
Symfony2 en pièces détachéesHugo Hamon
 
Introduction à Symfony2
Introduction à Symfony2Introduction à Symfony2
Introduction à Symfony2Hugo Hamon
 

Mehr von Hugo Hamon (14)

Design Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et Pimple
 
Monitor the quality of your Symfony projects
Monitor the quality of your Symfony projectsMonitor the quality of your Symfony projects
Monitor the quality of your Symfony projects
 
Database Design Patterns
Database Design PatternsDatabase Design Patterns
Database Design Patterns
 
Silex meets SOAP & REST
Silex meets SOAP & RESTSilex meets SOAP & REST
Silex meets SOAP & REST
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistence
 
Intégration Continue PHP avec Jenkins CI
Intégration Continue PHP avec Jenkins CIIntégration Continue PHP avec Jenkins CI
Intégration Continue PHP avec Jenkins CI
 
Symfony2 - extending the console component
Symfony2 - extending the console componentSymfony2 - extending the console component
Symfony2 - extending the console component
 
Développeurs, cachez-moi ça ! (Paris Web 2011)
Développeurs, cachez-moi ça ! (Paris Web 2011)Développeurs, cachez-moi ça ! (Paris Web 2011)
Développeurs, cachez-moi ça ! (Paris Web 2011)
 
Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2
 
Symfony2 - Un Framework PHP 5 Performant
Symfony2 - Un Framework PHP 5 PerformantSymfony2 - Un Framework PHP 5 Performant
Symfony2 - Un Framework PHP 5 Performant
 
Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2
 
Intégration continue des projets PHP avec Jenkins
Intégration continue des projets PHP avec JenkinsIntégration continue des projets PHP avec Jenkins
Intégration continue des projets PHP avec Jenkins
 
Symfony2 en pièces détachées
Symfony2 en pièces détachéesSymfony2 en pièces détachées
Symfony2 en pièces détachées
 
Introduction à Symfony2
Introduction à Symfony2Introduction à Symfony2
Introduction à Symfony2
 

Exposer des services web SOAP et REST avec symfony 1.4 et Zend Framework

  • 1. Exposer des services web SOAP et REST RMLL - 6 juillet 2010 Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 2. Qui suis-je ? ❖ Hugo HAMON (@hhamon) ❖ Responsable des formations chez Sensio Labs ❖ Coauteur et contributeur d’ouvrages ❖ Secrétaire Général de l’AFUP ❖ Webmaster du site Apprendre-PHP.com ❖ http://www.hugohamon.com Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 3. Introduction aux Web services Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 4. Les services web ❖ Programmes destinés à échanger des données entre systèmes hétérogènes ❖ Basés sur des standards (SOAP) ou des styles d’architecture (REST) ❖ Fonctionnent en mode Client / Serveur (requête / réponse) ❖ Echange de données préformattées (XML, JSON, YAML, HTML...) ❖ Faible couplage grâce aux standards ouverts comme XML ❖ Faciles à mettre en oeuvre Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 5. Architecture REST Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 6. REST c’est quoi ? ❖ REpresentational State Transfert ❖ Concept inventé par Roy Fielding en 2000 ❖ REST est un style d’architecture ! ❖ REST s’appuie sur les concepts suivants : ❖ Le protocole HTTP (requête / réponse) ❖ La notion d’URI qui identifie chaque ressource ❖ Les méthodes HTTP (GET, POST, PUT, DELETE, HEAD) ❖ Les codes de statut (200, 201, 403, 404, 500...) ❖ Les formats ouverts (XML, JSON, HTML...) ❖ REST est simple à mettre en oeuvre Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 7. La notion d’URI dans REST ❖ Chaque URI identifie une ressource http://api.domain.com/users/hugo ❖ Une URI ne contient pas de verbe ! ❖ Une même URI peut être appelée avec différentes méthodes HTTP GET http://api.domain.com/users Récupère les utilisateurs POST http://api.domain.com/users Crée un nouvel utilisateur Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 8. Les méthodes HTTP ❖ GET, POST, PUT, DELETE et HEAD ❖ Identifient les actions réalisables sur la ressource GET http://api.domain.com/users Récupère les utilisateurs POST http://api.domain.com/users Crée un nouvel utilisateur PUT http://api.domain.com/users/hugo Modifie hugo DELETE http://api.domain.com/users/hugo Supprime hugo ❖ Opérations CRUD sur les ressources Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 9. Les codes HTTP de retour ❖ Indiquent l’état (succès ou échec) de l’opération effectuée Méthodes En cas de succès En cas d’échec 201 Created POST 400 Bad Request Redirection vers l’URI de l’objet 400 Bad Request PUT 200 OK 404 Not Found 409 Conflict 400 Bad Request DELETE 200 OK 404 Not Found 410 Gone GET 200 OK 400 Bad Request 404 Not Found Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 10. Symfony un framework RESTfull Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 11. Introduction Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 12. Présentation de symfony ❖ Framework PHP 5 MVC Open Source « full stack » ❖ Rapid Application Development ❖ Publié en 2005 sous licence MIT ❖ Bâti pour répondre à des besoins complexes ❖ « best practices » (design patterns, mvc, tests unitaires...) ❖ Maintenu par Sensio Labs jusqu’à fin 2012 ❖ Documentation riche et Open Source (4 livres officiels) ❖ Communauté très active Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 13. Outillage de symfony MVC Propel CLI (CRUD) Tests Automatisés ACL Plugins Cache I18N & L10N Doctrine RESTful routing Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 14. Un routing RESTFull Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 15. Routage de symfony ❖ Symfony découple les URLs du code (implémentation technique) /blog.php?section=symfony&article_id=18475 /blog/2008-01-30/symfony-happy-new-year ❖ Optimisation pour les moteurs de recherche ❖ URIs faciles à copier / coller, mémoriser ou bookmarker ❖ Masque l’implémentation technique (php, python, ruby ?) Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 16. Contraindre les routes aux méthodes HTTP ❖ sfRequestRoute permet de contraindre les URIs aux méthodes HTTP ❖ Une même URI peut être atteinte avec des méthodes HTTP différentes user_edit: class: sfRequestRoute url: /api/users/:username param: { module: user, action: update } requirements: { sf_method: put } Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 17. Contraindre les routes aux méthodes HTTP $ php symfony app:routes api Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 18. Contraindre les routes aux méthodes HTTP ❖ Symfony simule les requêtes PUT et DELETE depuis un navigateur ❖ Les formulaires embarquent un champ caché « sf_method » <form action="/api_dev.php/api/user/hugo" method="post"> <input type="hidden" value="put" name="sf_method"/> <input type="hidden" id="rmll_user_id" value="2" name="rmll_user[id]"/> <input type="hidden" id="rmll_user__csrf_token" value="94c132e7c771411590124aea52bb9d4f" name="rmll_user[_csrf_token]"/> <!-- ... --> </form> Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 19. Contraindre les routes aux méthodes HTTP $params = array( 'method' => 'delete', 'confirm' => 'Etes-vous sûr de vouloir supprimer cet objet ?' ); echo link_to('supprimer', 'user_delete', $object, $params); Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 20. Contraindre les routes aux méthodes HTTP $params = array( 'method' => 'delete', 'confirm' => 'Etes-vous sûr de vouloir supprimer cet objet ?' ); echo link_to('supprimer', 'user_delete', $object, $params); <li class="sf_admin_action_delete"><a href="/api_dev.php/api/user/hugo" onclick="if (confirm('Are you sure?')) { var f = document.createElement ('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'post'; f.action = this.href;var m = document.createElement ('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', 'sf_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_csrf_token'); m.setAttribute('value', 'f0271a52cca50e62df7deb1568f80489'); f.appendChild(m);f.submit (); };return false;">Supprimer</a></li> Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 21. Les routes d’objets user_edit Route Objet Doctrine RmllUser Base de données user_edit: class: sfDoctrineRoute url: /api/users/:username param: { module: user, action: update } options: { model: RmllUser, column: username, type: object } requirements: { sf_method: put } Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 22. Les routes d’objets public function executeUpdate(sfWebRequest $request) { $user = $this->getRoute()->getObject(); $form = new RmllUserForm($user, array(), false); $form->bind($request->getParameter('rmll_user')); $status = 400; if ($form->isValid()) { $form->save(); $status = 200; } $this->getResponse()->setStatusCode($status); return sfView::NONE; } Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 23. Les collections de routes d’objets ❖ sfDoctrineRouteCollection ou sfPropelRouteCollection ❖ Actions CRUD sur un objet de modèle user user_new user_create user_edit user_update user_delete user_show Collection de routes Base de données Objet Doctrine RmllUser Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 24. Les collections de routes d’objets user: class: sfDoctrineRouteCollection options: model: RmllUser module: user prefix_path: /api/users column: username with_wildcard_routes: true actions: [list, create, update, delete, show] Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 25. Les collections de routes d’objets Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 26. Support des formats de sortie Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 27. Support des formats de sortie ❖ Par défaut, symfony supporte le format HTML ❖ Le paramètre « sf_format » définit le format de sortie ❖ Symfony se charge d’envoyer les bons en-têtes en fonction de l’extension user: class: sfDoctrineRouteCollection options: model: RmllUser module: user prefix_path: /api/users column: username with_wildcard_routes: true actions: [list, create, update, delete, show] requirements: { sf_format: (?:html|xml|json) } Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 28. http://api.domain.com/users/hugo.xml Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 29. http://api.domain.com/users/hugo.xml executeShow($request) Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 30. http://api.domain.com/users/hugo.xml executeShow($request) showSuccess.php showSuccess.xml.php showSuccess.json.php Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 31. http://api.domain.com/users/hugo.xml executeShow($request) showSuccess.php showSuccess.xml.php showSuccess.json.php Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 32. <h1><?php echo $user ?></h1> <table> showSuccess.php <tbody> <tr> <td>Username</td> <td><?php echo $user->getUsername() ?></td> </tr> <tr> <td>Password</td> <td><?php echo $user->getPassword() ?></td> </tr> <tr> <td>First name</td> <td><?php echo $user->getFirstName() ?></td> </tr> <tr> <td>Last name</td> <td><?php echo $user->getLastName() ?></td> </tr> <tr> <td>Birthdate</td> <td><?php echo $user->getBirthdate() ?></td> </tr> </tbody> </table> Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 33. <?php echo '<?xml version="1.0" encoding="UTF-8" ?>'."n" ?> <user> <username><?php echo $user->getUsername() ?></username> <firstName><?php echo $user->getFirstName() ?></firstName> <lastName><?php echo $user->getLastName() ?></lastName> <birthdate><?php echo $user->getBirthdate() ?></birthdate> </user> showSuccess.xml.php showSuccess.json.php { "username": <?php echo json_encode($user->getUsername()) ?>, "firstName": <?php echo json_encode($user->getFirstName(ESC_RAW)) ?>, "lastName": <?php echo json_encode($user->getLastName(ESC_RAW)) ?>, "birthdate": <?php echo json_encode($user->getBirthdate()) ."n" ?> } Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 34. Sortie HTML Sortie XML Sortie JSON Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 35. Cache des résultats Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 36. Cache des résultats ❖ Symfony dispose nativement d’un cache HTML des pages ❖ Chaque sortie générée peut être mise en cache sur le serveur ❖ La durée de vie du cache de chaque page est configurable ❖ Le cache est par défaut stocké sur le système de fichier (sfFileCache) ❖ Symfony offre la possibilité de choisir où stocker le cache : ❖ Fichiers (sfFileCache) ❖ SQLite (sfSQLiteCache) ❖ XCache (sfXCacheCache) ❖ MemCache (sfMemCacheCache) ❖ APC... (sfAPCCache) Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 37. Cache des résultats ❖ apps/api/modules/user/config/cache.yml show: enabled: true with_layout: true lifetime: 3600 Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 38. Avant la mise en cache 336 ms Après la mise en cache 50 ms Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 39. Tests Fonctionnels de l’API Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 40. Simuler des requêtes GET include(dirname(__FILE__).'/../../bootstrap/functional.php'); $browser = new RmllTestFunctional(new sfBrowser()); $browser->loadFixtures(); $browser-> get('/api/users/hhamon.xml')-> with('request')->begin()-> isFormat('xml')-> isParameter('module', 'user')-> isParameter('action', 'show')-> end()-> with('response')->begin()-> isStatusCode(200)-> isValid()-> end(); Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 41. Simuler des requêtes GET include(dirname(__FILE__).'/../../bootstrap/functional.php'); $browser = new RmllTestFunctional(new sfBrowser()); $browser->loadFixtures(); $browser-> get('/api/users/hhamon.xml')-> GET sur le fichier XML with('request')->begin()-> isFormat('xml')-> isParameter('module', 'user')-> isParameter('action', 'show')-> end()-> with('response')->begin()-> isStatusCode(200)-> isValid()-> end(); Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 42. Simuler des requêtes GET include(dirname(__FILE__).'/../../bootstrap/functional.php'); $browser = new RmllTestFunctional(new sfBrowser()); $browser->loadFixtures(); $browser-> get('/api/users/hhamon.xml')-> GET sur le fichier XML with('request')->begin()-> isFormat('xml')-> isParameter('module', 'user')-> Vérification de la requête isParameter('action', 'show')-> end()-> with('response')->begin()-> isStatusCode(200)-> isValid()-> end(); Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 43. Simuler des requêtes GET include(dirname(__FILE__).'/../../bootstrap/functional.php'); $browser = new RmllTestFunctional(new sfBrowser()); $browser->loadFixtures(); $browser-> get('/api/users/hhamon.xml')-> GET sur le fichier XML with('request')->begin()-> isFormat('xml')-> isParameter('module', 'user')-> Vérification de la requête isParameter('action', 'show')-> end()-> with('response')->begin()-> isStatusCode(200)-> Vérification de la réponse isValid()-> end(); Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 44. Simuler des requêtes GET Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 45. $user = array( 'username' => 'pmartin', 'password' => 'something', 'first_name' => 'Paul', 'last_name' => 'Martin' ); $user = getUser(array('birthdate' => '')); $browser-> post('/api/users', array('rmll_user' => $user))-> with('response')->isStatusCode(400); $browser-> post('/api/users', array('rmll_user' => getUser()))-> with('response')->begin()-> isStatusCode(201)-> isRedirected()-> end()-> followRedirect() Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 46. $user = array( 'username' => 'pmartin', 'password' => 'something', 'first_name' => 'Paul', 'last_name' => 'Martin' ); $user = getUser(array('birthdate' => '')); $browser-> post('/api/users', array('rmll_user' => $user))-> with('response')->isStatusCode(400); $browser-> post('/api/users', array('rmll_user' => getUser()))-> with('response')->begin()-> isStatusCode(201)-> isRedirected()-> end()-> followRedirect() Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 47. $user = array( 'username' => 'pmartin', 'password' => 'something', 'first_name' => 'Paul', Test de la création avec des 'last_name' => 'Martin' paramètres manquants ); $user = getUser(array('birthdate' => '')); $browser-> post('/api/users', array('rmll_user' => $user))-> with('response')->isStatusCode(400); $browser-> post('/api/users', array('rmll_user' => getUser()))-> with('response')->begin()-> isStatusCode(201)-> isRedirected()-> end()-> followRedirect() Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 48. $user = array( 'username' => 'pmartin', 'password' => 'something', 'first_name' => 'Paul', Test de la création avec des 'last_name' => 'Martin' paramètres manquants ); $user = getUser(array('birthdate' => '')); $browser-> post('/api/users', array('rmll_user' => $user))-> with('response')->isStatusCode(400); $browser-> post('/api/users', array('rmll_user' => getUser()))-> with('response')->begin()-> isStatusCode(201)-> isRedirected()-> end()-> followRedirect() Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 49. $user = array( 'username' => 'pmartin', 'password' => 'something', 'first_name' => 'Paul', Test de la création avec des 'last_name' => 'Martin' paramètres manquants ); $user = getUser(array('birthdate' => '')); $browser-> post('/api/users', array('rmll_user' => $user))-> with('response')->isStatusCode(400); $browser-> post('/api/users', array('rmll_user' => getUser()))-> with('response')->begin()-> isStatusCode(201)-> isRedirected()-> end()-> followRedirect() Test de la création avec des paramètres valides Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 50. Simuler des requêtes POST Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 51. Simuler des requêtes PUT $user = getUser(array('first_name' => 'Toto')); $browser-> call('/api/users/pmartin', 'put', array('rmll_user' => $user))-> with('response')->isStatusCode(200) ; Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 52. Simuler des requêtes PUT $user = getUser(array('first_name' => 'Toto')); $browser-> call('/api/users/pmartin', 'put', array('rmll_user' => $user))-> with('response')->isStatusCode(200) ; Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 53. Simuler des requêtes DELETE $browser-> call('/api/users/pmartin', 'delete')-> with('response')->isStatusCode(200); Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 54. Simuler des requêtes DELETE $browser-> call('/api/users/pmartin', 'delete')-> with('response')->isStatusCode(200); Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 55. Architecture SOAP Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 56. Introduction à SOAP Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 57. Qu’est-ce que SOAP ? ❖ « Simple Object Access Protocol » ❖ SOAP est un protocole standard (http://www.w3.org/TR/soap/) ❖ Appel de procédure à distance reposant sur un standard XML ❖ SOAP permet d’invoquer des méthodes sur un objet distant ❖ La réponse est servie au client SOAP sous forme d’une réponse SOAP XML ❖ Transport des requêtes et réponses SOAP avec le protocole HTTP ❖ Les requêtes et réponses SOAP sont des chaînes XML ❖ Les données sont traitées sur le serveur puis converties en XML Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 58. Avantages et Inconvénients ❖ Avantages : ❖ Inconvénients : ✤ Standard éprouvé ✤ Lourd et lent ✤ Indépendant de la plateforme ✤ Verbosité du XML ✤ Indépendant du langage ✤ Difficile à tester et à cacher ✤ Extensible Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 59. Fonctionnement de SOAP http://domain.com/service?wsdl http://domain.com/service SOAP Client SOAP Serveur $service = new FooService(); $response = $s->calledMethod($param1, $param2); Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 60. Exposer des services SOAP avec symfony et Zend Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 61. class ProjectConfiguration extends sfProjectConfiguration { static protected $zendLoaded = false; public function setup() { $this->enablePlugins('sfDoctrinePlugin'); self::registerZend(); } static public function registerZend() { if (self::$zendLoaded) { return; } set_include_path( sfConfig::get('sf_lib_dir').'/vendor'.PATH_SEPARATOR.get_include_path() ); require_once sfConfig::get('sf_lib_dir').'/vendor/Zend/Loader/Autoloader.php'; Zend_Loader_Autoloader::getInstance(); self::$zendLoaded = true; } } Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 62. class ProjectConfiguration extends sfProjectConfiguration { static protected $zendLoaded = false; Framework Zend dans public function setup() lib/vendor/Zend { $this->enablePlugins('sfDoctrinePlugin'); self::registerZend(); } static public function registerZend() { if (self::$zendLoaded) { return; } set_include_path( sfConfig::get('sf_lib_dir').'/vendor'.PATH_SEPARATOR.get_include_path() ); require_once sfConfig::get('sf_lib_dir').'/vendor/Zend/Loader/Autoloader.php'; Zend_Loader_Autoloader::getInstance(); self::$zendLoaded = true; } } Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 63. class ProjectConfiguration extends sfProjectConfiguration { static protected $zendLoaded = false; Framework Zend dans public function setup() lib/vendor/Zend { $this->enablePlugins('sfDoctrinePlugin'); self::registerZend(); } static public function registerZend() Initialisation de { if (self::$zendLoaded) { l’autoloader de Zend return; } set_include_path( sfConfig::get('sf_lib_dir').'/vendor'.PATH_SEPARATOR.get_include_path() ); require_once sfConfig::get('sf_lib_dir').'/vendor/Zend/Loader/Autoloader.php'; Zend_Loader_Autoloader::getInstance(); self::$zendLoaded = true; } } Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 64. Création d’un module et d’une route ❖ Création d’un nouveau module converter $ php symfony generate:module api converter ❖ Création d’une nouvelle route converter_service dans routing.yml converter_service: url: /converter/service param: { module: converter, action: index } Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 65. class TemperatureConverterService { /** * Converts a Celsius temperature into a Fahrenheit temperature. * * @param float $value The value to convert * @return float */ public function convertCelsiusToFahrenheit($value) { return 1.8 * $value + 32; } /** * Converts a Fahrenheit temperature into a Celsius temperature. * * @param float $value The value to convert * @return float */ public function convertFahrenheitToCelsius($value) { return (5/9) * $value - 160/9; } } PHPDoc importante Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 66. Dévoiler le WSDL public function executeWsdl(sfWebRequest $request) { try { $wsdl = new Zend_Soap_AutoDiscover(); $wsdl->setClass('TemperatureConverterService'); $wsdl->handle(); } catch (Exception $e) { $this->logMessage($e->getMessage()); } return sfView::NONE; } Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 67. Dévoiler le WSDL public function executeWsdl(sfWebRequest $request) { try { $wsdl = new Zend_Soap_AutoDiscover(); $wsdl->setClass('TemperatureConverterService'); $wsdl->handle(); } catch (Exception $e) { $this->logMessage($e->getMessage()); } return sfView::NONE; Zend génère le WSDL par } introspection de la PHPDoc de la classe du service Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 68. http://api.domain.com/converter/service?wsdl Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 69. Implémenter la passerelle du service public function executeIndex(sfWebRequest $request) { $this->forwardIf(null !== $request->getParameter('wsdl'), 'converter', 'wsdl'); try { $wsdl = $this->generateUrl('converter_service', array(), true).'?wsdl'; $server = new Zend_Soap_Server($wsdl); $server->setClass('TemperatureConverterService'); $server->setReturnResponse(true); $this->renderText($server->handle()); } catch (Exception $e) { $this->logMessage($e->getMessage()); } return sfView::NONE; } Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 70. Consommer le service SOAP Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 71. Consommer le service SOAP try { $client = new Zend_Soap_Client( 'http://api.domain.com/converter/service?wsdl' ); $celsiusToFahrenheit = $client->convertCelsiusToFahrenheit(30.50); $fahrenheitToCelsius = $client->convertFahrenheitToCelsius(72.30); } catch (SoapFault $e) { exit($e->getMessage()); } echo $celsiusToFahrenheit; echo $fahrenheitToCelsius; Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 72. Tester le service SOAP Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 73. Tester le service SOAP ❖ Tester un service SOAP avec PHP est assez compliqué ! ❖ La requête et la réponse doivent être testées ❖ Les réponses doivent être simulées (mock) ❖ Zend_Soap a l’avantage d’être déjà testé par Zend ❖ Le fonctionnement de symfony est déjà testé également ❖ A tester unitairement : la classe TemperatureConverterService Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 74. Tests unitaires du service // test/unit/service/TemperatureConverterServiceTest.php require dirname(__FILE__).'/../../bootstrap/unit.php'; $t = new lime_test(3); $service = new TemperatureConverterService(); $t->diag('->convertCelsiusToFahrenheit()'); $result = $service->convertCelsiusToFahrenheit(0); $t->is($result, 32, '->convertCelsiusToFahrenheit() returns 32'); $result = $service->convertCelsiusToFahrenheit(1); $t->is($result, 33.8, '->convertCelsiusToFahrenheit() returns 33.8'); $result = $service->convertCelsiusToFahrenheit(10); $t->is($result, 50, '->convertCelsiusToFahrenheit() returns 50'); Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 75. Tests unitaires du service $ php symfony test:unit TemperatureConverterService Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 76. Tests unitaires du service // test/unit/service/TemperatureConverterServiceTest.php require dirname(__FILE__).'/../../bootstrap/unit.php'; $t = new lime_test(6); $service = new TemperatureConverterService(); // ... $t->diag('->convertFahrenheitToCelsius()'); $result = $service->convertFahrenheitToCelsius(0); $t->is($result, -160/9, '->convertFahrenheitToCelsius() returns -160/9'); $result = $service->convertFahrenheitToCelsius(33.8); $t->is($result, 1, '->convertFahrenheitToCelsius() returns 1'); $result = $service->convertFahrenheitToCelsius(50); $t->is($result, 10, '->convertFahrenheitToCelsius() returns 10'); Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 77. Tests unitaires du service $ php symfony test:unit TemperatureConverterService Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010
  • 78. Questions ? Sensio Labs recrute ! hugo.hamon@sensio.com Sensio Labs Workshop www.symfony-project.org trainings.sensiolabs.com mardi 6 juillet 2010