Grégoire Hébert

Lead-Developper & Formateur @ Les-Tilleuls.coop
@gheb_dev

Dev/consulting/training - Lille/Paris/Amiens

👊 Auto-gérée depuis 2011

⬆ 97% en 2016, 23 employés modèles

👷 ➡ jobs@les-tilleuls.coop

         masterclass@les-tilleuls.coop

Le web évolue !

  • De plus en plus de Javascript webapps, et Google est capable de les parcourir.
     
  • Les utilisateurs passent plus de temps sur mobile que sur leur machine: des sites responsive, ou des apps mobile sont plus que nécessaire.
     
  • JSON-LD, Schema.org, Hydra: Linked Data & le web semantic sont de plus en plus utilisé.

API, le nouveau cœur du web

  • Un seul point d'accès aux données
  • Encapsulation de la logique métier
  • Homogénéité des données pour tous les supports.

API Platform

A framework for the new API-first web

3 composants !

 

  • Une API web
  • Une Application web statique (SPA)
  • Une Administration web dynamique

L'API web

  • Lecture / Écriture centralisée des données
  • Contient toute la logique métier
  • Conçue avec PHP & API-Platform
  • Stateless pour une meilleure expansion horizontale sans contrainte de session.

L'application web

Ou tout autre client (mobile, etc...)

  • Détiennent la logique de présentation
  • sont chargées une seule fois (Single Page Application)
  • Requêtent l'API pour recevoir ou modifier les données en AJAX
  • Uniquement composée d'HTML, Javascript, et assets CSS
  • Peuvent être hébergées sur un CDN

L'admin web

  • Permet de gérer vos données
  • Est générée dynamiquement grâce à la doc Hydra
  • Ne contient aucune logique métier
  • Est écrite en React avec Admin-on-rest
  • Peut être hébergée sur un CDN

StandAlone

  • 1 dépôt pour les rassembler (et dans les ténèbres les lier)
  • 3 domaines
  • Le routing est réalisé côté client.

s les

Bénéfices immédiats

Rapide

  • les Assets sont chargés depuis un CDN
  • Plus aucun chargement par la suite si ce n'est le strict nécessaire pour chaque requête
  • quantité de données en transit minimisée
  • Les réponses de l'API peuvent être mises en cache par le proxy

Extensible et robuste

  • L'application frontale n'est qu'un jeu de fichiers statiques.
     
  • API Stateless : Ajout et suppression de serveurs / conteneurs sur demande

Confort de développement

  • Un formulaire pour générer le code ? Faites-le en JS, oubliez les formulaires Symfony.
     
  • Ré-utilisez votre API pour tous vos besoins : App mobile native, App TV, Appareil connecté, ou client bureau.
     
  • Donnez accès à vos utilisateurs et partenaires un accès aux données brutes à travers l'API

Bénéfices à long terme

  • Une structure éprouvée : La centralisation de l'API, c'est aussi la centralisation de la logique métier. Moins de duplications lorsque votre application grandit.
     
  • Refactoring facilité : Modifier un composant n'impacte pas les autres.
     
  • Gestion de projet simplifiée : différentes équipes peuvent travailler sur les différentes app.

Formats, (open) standards, patterns

HTTP + REST + JSON

  • Fonctionne sur toutes les plaformes
  • Léger
  • Stateless
  • HTTP possède un puissant système de cache
  • Extensible (JSON-LD, Hydra, Swagger, HAL...)
  • Il existe de nombreux outils de développement

HTTP + REST + JSON

HTTP/2

HATEOAS / Linked Data

Hypermedia as the Engine of Application State

  • Hypermedia: IRI comme identifiant
  • Possibilité de référencer des données externes (liens hypertexte par exemple)
  • clients génériques

JSON-LD

Json for Linked data

  • Standard W3C depuis 2014
  • Facile, c'est du json !
  • Déjà utilisé par Gmail, GitHub, BBC, Microsoft...
  • Adapté aux technologies du web sémantique : RDF, SPARQL, triple store...
{
  "@context": "/contexts/PostalAddress",
  "@id": "/postal_addresses",
  "@type": "hydra:PagedCollection",
  "hydra:totalItems": 1,
  "hydra:itemsPerPage": 30,
  "hydra:firstPage": "/postal_addresses",
  "hydra:lastPage": "/postal_addresses",
  "hydra:member": [
    {
      "@id": "/postal_addresses/1",
      "@type": "http://schema.org/PostalAddress",
      "id": 1,
      "addressCountry": "France",
      "postalCode": "75008",
      "streetAddress": "6 Rue Balzac"
    }
  ]
}

JSON-API

  • Format Hypermedia
  • Facile, c'est du json aussi !
  • /!\ Ce n'est pas un standard !
api_platform:
    # ...
    formats:
        # ...
        jsonapi: ['application/vnd.api+json']
    error_formats:
        # ...
        jsonapi: ['application/vnd.api+json']

JSON-API

{
  "links": {
    "self": "http://example.com/articles",
    "next": "http://example.com/articles?page[offset]=2",
    "last": "http://example.com/articles?page[offset]=10"
  },
  "data": [{
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "JSON API paints my bikeshed!"
    },
    "relationships": {
      "author": {
        "links": {
          "self": "http://example.com/articles/1/relationships/author",
          "related": "http://example.com/articles/1/author"
        },
        "data": { "type": "people", "id": "9" }
      },
      "comments": {
        "links": {
          "self": "http://example.com/articles/1/relationships/comments",
          "related": "http://example.com/articles/1/comments"
        },
        "data": [
          { "type": "comments", "id": "5" },
          { "type": "comments", "id": "12" }
        ]
      }
    },
    "links": {
      "self": "http://example.com/articles/1"
    }
  }],
  "included": [{
    "type": "people",
    "id": "9",
    "attributes": {
      "first-name": "Dan",
      "last-name": "Gebhardt",
      "twitter": "dgeb"
    },
    "links": {
      "self": "http://example.com/people/9"
    }
  }, {
    "type": "comments",
    "id": "5",
    "attributes": {
      "body": "First!"
    },
    "relationships": {
      "author": {
        "data": { "type": "people", "id": "2" }
      }
    },
    "links": {
      "self": "http://example.com/comments/5"
    }
  }, {
    "type": "comments",
    "id": "12",
    "attributes": {
      "body": "I like XML better"
    },
    "relationships": {
      "author": {
        "data": { "type": "people", "id": "9" }
      }
    },
    "links": {
      "self": "http://example.com/comments/12"
    }
  }]
}

Schema.org

  • Défini un large panel d'éléments : people, creative work, events, products, chemicals...
  • Créé et interprếté par Google, Bing, Yahoo! et Yandex
  • Massivement utilisé, et suivi par le W3C
  • Peut être utilisé avec le HTML, RDF et JSON-LD
  • Peut être étendu (Vocabulaire personnalisé)

Schema.org

{
  "@context": "http://schema.org",
  "@id": "/postal_addresses/1",
  "@type": "http://schema.org/PostalAddress",
  "id": 1,
  "addressCountry": "France",
  "postalCode": "75008",
  "streetAddress": "6 Rue Balzac"
}

Hydra

  • Décrit une API REST avec du JSON-LD
  • Permet l'écriture de données
  • Permet de découvrir automatiquement l'API 
  • Draft W3C (Work In Progress)

Autres formats supportés

  • Swagger
  • HAL
  • API Problem
  • raw JSON
  • CSV
  • YAML
  • XML

API Platform <3 Symfony

 

  • Conçu à partir de Symfony flex
  • Installez n'importe quel Bundle SF existant
  • Suit les bonnes pratiques SF
  • Intégrable dans une application existante SF
  • (Optionnel) Optimisé pour doctrine

API Platform 2.2:
ce qui change

  • Symfony Standard Edition  =>  Symfony Flex
  • MySQL => PostgreSQL par défaut
  • HTTP/2 et HTTPS dev proxy
  • Container pour les dev JS 
  • Structure simplifiée
  • GraphQL
  • Générateur Client React & Vue
  • Déploiement "rapide" sur Kubernetes
  • Amélioration des filtres
  • Cache intégré par invalidation (varnish / cloudflare)
  • Support de Json-API
  • Ajout du Partial Paginator

API Platform <3 GraphQL

Partial Paginator

# app/config/config.yml
api_platform:
    collection:
        pagination:
            partial: false # Default value
            client_partial: false # Default value
            partial_parameter_name: 'partial' # Default value

Filters

# api_platform.yaml
services:
    offer.search_filter:
        parent: 'api_platform.doctrine.orm.search_filter'
        arguments: [ { id: 'exact', price: 'exact', name: 'partial' } ]
        tags: [ 'api_platform.filter' ]

<?php
// src/AppBundle/Entity/Offer.php

namespace AppBundle\Entity;

use ApiPlatform\Core\Annotation\ApiResource;

/**
 * @ApiResource(attributes={"filters"={"offer.search_filter"}})
 */
class Offer
{
    // ...
}
<?php
// src/AppBundle/Entity/Offer.php

namespace AppBundle\Entity;

use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiFilter;

/**
 * @ApiResource
 * @ApiFilter(SearchFilter::class, strategy="partial")
 */
class Offer
{
    // ...
}

Créer une API

$ wget https://github.com/api-platform/api-platform/archive/v2.2.0-beta.1.tar.gz
$ tar xzvf v2.2.0-beta.1.tar.gz
$ cd api-platform-2.2.0

Téléchargez le projet

ou bien utilisez flex

$ composer create-project symfony/skeleton MyProject
$ composer req api
# Start Docker
$ docker-compose up -d

# Création de la bdd
$ docker-compose exec php bin/console doctrine:schema:create

Démarrage du projet

Vous obtenez :

 

  • Support CRUD des relations et données
  • Validation des données
  • Pagination de collections
  • Gestion de la sérialisation 
  • Gestion dynamique des routes
  • Propriétés exposées filtrables
  • Sorting
  • Point d'entrée Hypermedia

Le bundle expose les données grâce aux metadata suivantes:

 

  • Doctrine ORM
  • Validator constraints
  • Serializer groups
  • PHPDoc
  • Vos propres Metadata Loaders

Support complet de JSONAPI, JSON-LD, Hydra et Schema.org

API de données auto-decouvrable !

Documentation et Sandbox

Swagger UI Détecte et documente automatiquement les ressources exposées.

Génération dynamique d'admin

L'admin s'appuie sur la documentation Hydra pour générer les opérations CRUD nécessaire !

Génération de client statique

Le client s'appuie sur la documentation Hydra pour générer les vues et composants REACT !

La preuve par 3

La preuve par 3

La stack js

  • React
  • ES2015 + JSX
  • React Router: client-side routing library
  • Redux: extensible container to manage the states of the app
  • Redux Form: forms Redux
  • Thunk: async actions (AJAX requests)
  • Optional: Twitter Bootstrap

La preuve par 3

Les autre squelettes

  • React Native: master branch (@mysiar)
  • TypeScript definitions: master branch (@soyuka)
  • Angular: community (momenttech/lysis)
  • Vue.js: api-platform/client-generator#35 (@alOneh)
  • Vous en voulez plus ? Les PR sont appréciées :)

La preuve par 3

Kubernetes

$ helm install ./api/helm/api --name api

Le projet est déployé, managé
et scalé (j'avais plus le mot français)

MERCI !
Des questions ?

Made with Slides.com