Faire un client API en moins de 5min !

Baptiste Leduc

Baptiste Leduc

- 🐘 Développeur PHP

-       Antenne AFUP Paris

- 🏂 Wakeboard

- 🌱 Maintainer Jane

-       github.com/Korbeil

-       twitter.com/Korbeil_

Jane 🤔

Permet de décrire et valider des documents JSON.

JsonSchema

{
  "$id": "https://example.com/geographical-location.schema.json",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Longitude and Latitude Values",
  "description": "A geographical coordinate.",
  "required": [
    "latitude",
    "longitude"
  ],
  "type": "object",
  "properties": {
    "latitude": {
      "type": "number",
      "minimum": -90,
      "maximum": 90
    },
    "longitude": {
      "type": "number",
      "minimum": -180,
      "maximum": 180
    }
  }
}

OpenApi

- Anciennement Swagger

- Utilisé pour décrire des API 

openapi: "3.0.0"
paths:
  /pets:
    get:
      operationId: listPets
      parameters:
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            format: int32
      responses:
        '200':
          content:
            application/json:    
              schema:
                $ref: "#/components/schemas/Pets"
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    post:
      summary: Create a pet
      operationId: createPets
      tags:
        - pets
      responses:
        '201':
          description: Null response
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /pets/{petId}:
    get:
      summary: Info for a specific pet
      operationId: showPetById
      tags:
        - pets
      parameters:
        - name: petId
          in: path
          required: true
          description: The id of the pet to retrieve
          schema:
            type: string
      responses:
        '200':
          description: Expected response to a valid request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Pet"
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
components:
  schemas:
    Pet:
      type: object
      required:
        - id
        - name
      properties:
        id:
          type: integer
          format: int64
        name:
          type: string
        tag:
          type: string
    Pets:
      type: array
      items:
        $ref: "#/components/schemas/Pet"
    Error:
      type: object
      required:
        - code
        - message
      properties:
        code:
          type: integer
          format: int32
        message:
          type: string

À l'intérieur 🔎

Une API, CatFacts 🐈

Le schéma 📝

Parfois l'API que l'on veut utiliser n'a pas de schéma disponible. On doit donc le créer à partir de zéro comme ici.

 

Souvent vous pourrez trouver un schéma pour les API que vous utilisez au quotidien :

- Slack slackapi/slack-api-specs

- Stripe stripe/openapi

openapi: 3.0.2
info:
  version: 1.0.0
  title: 'CatFacts API'
servers:
  - url: https://cat-fact.herokuapp.com
paths:
  /facts/random:
    get:
      operationId: randomFact
      responses:
        200:
          description: 'Get a random `Fact`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Fact'
components:
  schemas:
    Fact:
      type: object
      properties:
        _id:
          type: string
          description: 'Unique ID for the `Fact`'
        __v:
          type: integer
          description: 'Version number of the `Fact`'
        user:
          type: string
          description: 'ID of the `User` who added the `Fact`'
        text:
          type: string
          description: 'The `Fact` itself'
        updatedAt:
          type: string
          format: date-time
          description: 'Date in which `Fact` was last modified'
        sendDate:
          type: string
          description: 'If the `Fact` is meant for one time use, this is the date that it is used'
        deleted:
          type: boolean
          description: 'Weather or not the `Fact` has been deleted (Soft deletes are used)'
        source:
          type: string
          description: 'Can be `user` or `api`, indicates who added the fact to the DB'
        used:
          type: boolean
          description: 'Weather or not the `Fact` has been sent by the CatBot. This value is reset each time every `Fact` is used'
        type:
          type: string
          description: 'Type of animal the `Fact` describes (e.g. ‘cat’, ‘dog’, ‘horse’)'

Configuration 🔧

Une fois son schéma OpenApi trouvé, nous devons configurer Jane !

 

Il a besoin de plusieurs choses :

#!/usr/bin/env php
# .jane-openapi
<?php

return [
  'openapi-file' => __DIR__ . '/schema.yaml',
  'namespace' => 'CatFacts\Api',
  'directory' => __DIR__ . '/generated/',
];

- Où est votre schéma ?

- Quel namespace appliquer aux classes générées ?

- Le dossier où mettre ses classes générées ?

Génération ! 🔄

$ rm -r generated/* && vendor/bin/jane-openapi generate

$ tree generated/
generated/
├── Client.php
├── Endpoint
│   └── RandomFact.php
├── Model
│   └── Fact.php
└── Normalizer
    ├── FactNormalizer.php
    └── NormalizerFactory.php

3 directories, 5 files

Utilisation 🎉

<?php 

require_once './vendor/autoload.php';

use CatFacts\Api\Client;

// on crée un client
$client = Client::create();

// on appelle un endpoint
$fact = $client->randomFact();
dump($fact);

Et après ? ...

Une fois que vous avez fait votre client API, rendez-le OpenSource !

 

Parce que si vous en avez eu besoin, d'autres en auront besoin aussi 😉

Merci 🕺👋

La démo est disponible sur le repo :

Made with Slides.com