Grégoire Hébert

@gheb_dev

Programme

  • Introduction
  • Créer une API
  • Générer un modèle de données à partir des vocabulaires ouverts
  • Générer une interface d'administration avec React
  • Générer une web app avec React
  • Déployer en production avec Docker et Kubernetes

Programme

  • Rappel sur les APIs : REST, HATEOAS, hypermedia, GraphQL
  • Les APIs au coeur du web aujourd’hui
  • JavaScript et les Progressive Web Apps
  • API Platform, Symfony et React
  • Les bénéfices immédiats

Programme

  • Mettre en place son environnement de développement avec Docker
  • Créer son modèle de données
  • Sérialiser ses données
  • Valider ses données
  • Filtrer ses données
  • Paginer ses données
  • Gérer des utilisateurs
  • Sécuriser ses données
  • Créer des opérations personnalisées
  • Se brancher aux évènements
  • Personnaliser la documentation OpenAPI
  • Personnaliser la documentation Hydra
  • Uploader des images
  • Tester son API avec Behat
  • Mettre en cache ses données

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 tout 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ée
  • 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étiens la logique de présentation
  • Est chargé une seule fois (Single Page Application
  • Requête l'API pour recevoir ou modifier les données en AJAX
  • Uniquement composé d'HTML, Javascript, et assets CSS
  • Peux être hébergée sur un CDN

L'admin web

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

StandAlone

  • 3 dépôt Git pour 3 projets et 3 CI
  • 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.

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 mise 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 duplication lorsque votre application grandi.
  • 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 cach
  • Extensible (JSON-LD, Hydra, Swagger, HAL...)
  • Il existe de nombreux outils de développement

HATEOAS / Linked Data

Hypermedia as the Engine of Application State

  • Hypermedia: IRI comme identifiant
  • Possibilité de référencer des données externe (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"
    }
  ]
}

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é)

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: La promesse

 

  • API avec support complet de Swagger + JSON-LD + Hydra + HAL en quelques minutes
  • Documentation auto-générée
  • Définition de spec et de tests avec Behat
  • Authentification avec JWT ou OAuth
  • CORS & cache HTTP
  • All the tools you love: Doctrine ORM, Monolog, Swiftmailer...
  • Un générateur de modèle grâce à Schema.org

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

Créer une API

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

Télécharger le squelette

ou bien utiliser composer

$ composer create-project api-platform/api-platform formation
# Start Docker
$ docker-compose up -d

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

Démarrage du projet

Sérialiser ses données

Créer votre première entité

<?php

declare(strict_types=1);

namespace App\Entity;

use ApiPlatform\Core\Annotation\ApiProperty;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ORM\Mapping as ORM;

/**
 * The mailing address.
 *
 * @see http://schema.org/PostalAddress Documentation on Schema.org
 *
 * @ORM\Entity
 * @ApiResource(iri="http://schema.org/PostalAddress")
 */
class PostalAddress
{
    /**
     * @ORM\Id
     * @ORM\Column(type="string")
     * @ORM\GeneratedValue(strategy="UUID")
     *
     * @var string
     */
    private $uuid;

    /**
     * @var string|null The country. For example, USA. You can also provide the two-letter \[ISO 3166-1 alpha-2 country code\](http://en.wikipedia.org/wiki/ISO\_3166-1).
     *
     * @ORM\Column(type="text", nullable=true)
     * @ApiProperty(iri="http://schema.org/addressCountry")
     */
    private $addressCountry;

    /**
     * @var string|null The postal code. For example, 94043.
     *
     * @ORM\Column(type="text", nullable=true)
     * @ApiProperty(iri="http://schema.org/postalCode")
     */
    private $postalCode;

    /**
     * @var string|null The street address. For example, 1600 Amphitheatre Pkwy.
     *
     * @ORM\Column(type="text", nullable=true)
     * @ApiProperty(iri="http://schema.org/streetAddress")
     */
    private $streetAddress;

    public function getId(): ?int
    {
        return $this->id;
    }

    public function setAddressCountry(?string $addressCountry): void
    {
        $this->addressCountry = $addressCountry;
    }

    public function getAddressCountry(): ?string
    {
        return $this->addressCountry;
    }

    public function setPostalCode(?string $postalCode): void
    {
        $this->postalCode = $postalCode;
    }

    public function getPostalCode(): ?string
    {
        return $this->postalCode;
    }

    public function setStreetAddress(?string $streetAddress): void
    {
        $this->streetAddress = $streetAddress;
    }

    public function getStreetAddress(): ?string
    {
        return $this->streetAddress;
    }
}

Créer la table associée

$ docker-compose exec php bin/console \
doctrine:schema:update --force
api-# \d+ postal_address
 id              | integer | not null  | plain    |              | 
 address_country | text    |           | extended |              | 
 postal_code     | text    |           | extended |              | 
 street_address  | text    |           | extended |              | 

La documentation

Est à jour !

http(s)://localhost:8080/

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

GET /postal_addresses

{
  "@context": "/contexts/PostalAddress",
  "@id": "/postal_addresses",
  "@type": "hydra:Collection",
  "hydra:member": [
    {
      "@id": "/postal_addresses/1",
      "@type": "http://schema.org/PostalAddress",
      "id": 1,
      "addressCountry": "France",
      "postalCode": "75008",
      "streetAddress": "6 Rue Balzac"
    }
  ],
  "hydra:totalItems": 1
}

Magie ?

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 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 !

Valider ses données

<?php

declare(strict_types=1);

namespace App\Entity;

use ...
use Symfony\Component\Validator\Constraints as Assert;

/**
 * The mailing address.
 *
 * @see http://schema.org/PostalAddress Documentation on Schema.org
 *
 * @ORM\Entity
 * @ApiResource(iri="http://schema.org/PostalAddress")
 */
class PostalAddress
{
    // ...

    /**
     * @var string|null The street address. For example, 1600 Amphitheatre Pkwy.
     *
     * @Assert\NotBlank
     *
     * @ORM\Column(type="text", nullable=true)
     * @ApiProperty(iri="http://schema.org/streetAddress")
     */
    private $streetAddress;


    // ...
}

C'est tout !

Made with Slides.com