Salut la famille, bienvenue dans mon premier tutoriel sur ce blog je remercie d'abord @alioukahere pour cette opportunité.
Dans ce tutoriel je vais vous parlez de comment documenter une API laravel avec OpenApi/Swagger.
Écrire de la documentation est contraignante. D'autant plus que cette dernière doit être régulièrement mise à jour au fur et à mesure que le projet évolue, ne faisant qu'accroître le côté fastidieux de la chose.
UN PEU D'HISTOIRE
La lumière de laravel
Documenter une API n'est pas plus aisé, toutes les requêtes et réponses différentes de chaque endPoint doivent être renseignées. De plus, une API n'est pas forcément à destination des développeurs, elle doit donc être facile à comprendre.
Dans cet article nous allons voir comment documenter une API développée en laravel . Pour ceux pour qui c'est la première fois de voir le mot LARAVEL faites un tour rapide sur ce site https://www.apprendre-laravel.fr/laraguide.
Cet article évidemment ne peut pas traiter toutes les notions liées à la documentation via OpenApi/Swagger d'un projet laravel.
Il existe heureusement plusieurs services pour documenter une api. Les plus populaires sont RAML, Apiary et Swagger.
- RAML : un language basé sur le YAML ;
- Swagger : du JSON ou du YAML ;
- Apiary : markdown (API Blueprint) ;
Je vais vous expliquer un peu la particularité de chacun de ces services.
RAML
RAML (RESTful API Modeling Language) est un langage vous permettant de désigner une API très rapidement en respectant les principes architecturaux de REST. RAML permet de respecter les contraintes tout en étant très facile à lire (il repose sur le langage YAML, format de présentation de données très facile à lire développé par Clark Evans en 2001).
Sa facilité de lecture lui permet d'être compréhensible par l'ensemble de la communauté des développeurs. En fait une API documenter grâce à RAML est définit dans un simple fichier. Dans ce dernier on peut voir immédiatement ce que cette dernière fait. Procédé ainsi permet d'avoir un système maintenable sur le long terme.
SWAGGER
Swagger en une phrase c'est un ensemble d'outils permettant d'aider les développeurs dans la conception, le build, la documentation et la consommation d'API.
En 2010, Swagger n'était qu'une spécification open source pour construire des API REST. A cela est venu se greffer divers outils, également open source, pour aider à implémenter et visualiser les API; on parle là de Swagger UI, Swagger Editor et Swagger Codegen.
En 2015, le projet Swagger est récupéré par Smartbear Software et la spécification swagger est renommée OpenAPI.
APIARY
Apiary est un langage orienté documentation créé pour décrire une API sous forme de texte brut (markdown). Étant simple à apprendre et à lire, cela facilite la collaboration avec tous les membres de l'équipe aussi bien les développeurs front-end que le product owner. Ainsi tout le monde peut modifier la documentation.
Mon choix s'est porté sur Open Api (SWAGGER) pour plusieurs raisons, premièrement je l'utilise au quotidien et la dernière raison la documentation est automatiquement générée à partir du code.
ON CODE QUAND ?
Commençons molo molo (délicatement) .....
Quand tu l'annonce la bonne nouvelle
Comme exemple allons consommer et documenter une api public , rien de mieux que de prendre cet Api https://api.covid19api.com
INSTALLER LARAVEL
$ composer create-project --prefer-dist laravel/laravel ApiLaravelWithOpenApi
Composer va nous installer la dernière version de laravel :
$ php artisan --version
Laravel Framework 8.x.x
INSTALLER SWAGGER
$ composer require "darkaonline/l5-swagger"
PUBLIER SWAGGER:
$ php artisan vendor:publish --provider "L5Swagger\L5SwaggerServiceProvider"
Une fois que la publication est succès, un fichier l5-swagger.php
est automatiquement crée dans le dossier config/
Tu viens de faire le plus dur
Ce l5-swagger.php
est le fichier qui va nous permettre de configurer notre documentation en personnalisant par exemple la route, le nom de notre api, l'interface web de la documentation… dans cet exemple nous allons juste utiliser l'interface par défaut.
Tu veux déjà voir ta doc, soit patient....
Activons la doc, pour ce faire ajoutons ces lignes de code dans le contrôleur principal (Controller.php
) comme suit :
class Controller extends BaseController
{ /**
* @OA\Info(
* version="1.0.0",
* title="Api covid19 Documentation",
* description="Implementation of Swagger with in Laravel",
* @OA\Contact(
* email="admin@admin.com"
* ),
* @OA\License(
* name="Apache 2.0",
* url="http://www.apache.org/licenses/LICENSE-2.0.html"
* )
* )
*
* @OA\Server(
* url=L5_SWAGGER_CONST_HOST,
* description="Demo API Server"
* )
*
*
*/
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}
Dans le fichier l5-swagger.php
désactiver les lignes de 194
à 196
comme suit :
'constants' => [
'L5_SWAGGER_CONST_HOST' => env('L5_SWAGGER_CONST_HOST', 'http://my-default-host.com'),
],
Ajouter cette ligne dans le fichier .env
qui représentera notre Base Url :
L5_SWAGGER_CONST_HOST='http://127.0.0.1:8000/api'
Créons notre propre Controller et ajoutons ces lignes
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ApiController extends Controller
{
/**
* @OA\Get(
* path="/v1/countries",
* operationId="getAllCountrie",
* tags={"Tests"},
* summary="Get List Of Countries",
* description="Returns all countries and associated provinces. The country_slug variable is used for country specific data",
* @OA\Response(
* response=200,
* description="Successful operation",
* @OA\MediaType(
* mediaType="application/json",
* )
* ),
* @OA\Response(
* response=401,
* description="Unauthenticated",
* ),
* @OA\Response(
* response=403,
* description="Forbidden"
* ),
* @OA\Response(
* response=400,
* description="Bad Request"
* ),
* @OA\Response(
* response=404,
* description="not found"
* ),
* )
*/
public function getAllCountries(){
//voir plus bas
}
}
Enfin nous allons régénérer notre doc :
$ php artisan l5-swagger:generate
Si tout passe avec succès lançons le projet:
$ php artisan serve
Et partons sur le lien http://127.0.0.1:8000/api/documentation vous devriez voir ceci:
Pour avoir plus d'information sur toute les annotations déjà utiliser jusqu'ici consulter le site officiel de swagger https://swagger.io/specification/
Comme mentionné plus haut nous allons consommer cette api https://api.covid19api.com qui a plusieurs endpoint, mais dans notre cas nous allons consommer et documenter trois(3) endpoint pour faire plus court.
- https://api.covid19api.com/countries: Renvoie tous les pays et provinces associées qui ont été touchés par la pandémie.
- https://api.covid19api.com/dayone/country/:country: Renvoie tous les cas par type de cas pour un pays à partir du premier cas enregistré. Les cas doivent être l'un des suivants: confirmé, guéri, décès.
- https://api.covid19api.com/total/country/:country: Renvoie tous les cas par type de cas pour un pays par jour à partir du premier cas.
Pour consommer notre api, créons d'abord une méthode pour se connecter a l'api.
Pour cela créons un Helper
dans le dossier App
pour la connexion à l'api.
Pour consommer une api en php/laravel
plusieurs possibilité s'offrent a nous, mais pour faire plus court nous allons utiliser la méthode CURL
.
<?php
function serviceApi($endpoint){
$url="https://api.covid19api.com/$endpoint";
$crl = curl_init();
curl_setopt($crl, CURLOPT_URL, $url);
curl_setopt($crl, CURLOPT_FRESH_CONNECT, true);
curl_setopt($crl, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($crl);
if(!$response){
die('Error: "' . curl_error($ch) . '" - Code: ' . curl_errno($ch));
}
return $response;
curl_close($crl);
}
Activation du helper
Ajouter cette ligne dans le fichier composer.json
"autoload": {
….
"files": [
"app/Helper.php"
]
},
Activer le helper a travers la commande
$ composer dump-autoload
Modifions notre Controller en appelant la méthode serviceApi
qui est déjà déclarer dans notre Helper.php
/**
* @OA\Get(
* path="/v1/countries",
* operationId="getAllCountrie",
* tags={"Tests"},
* summary="Get List Of Countries",
* description="Returns all countries and associated provinces. The country_slug variable is used for country specific data",
* @OA\Response(
* response=200,
* description="Successful operation",
* @OA\MediaType(
* mediaType="application/json",
* )
* ),
* @OA\Response(
* response=401,
* description="Unauthenticated",
* ),
* @OA\Response(
* response=403,
* description="Forbidden"
* ),
* @OA\Response(
* response=400,
* description="Bad Request"
* ),
* @OA\Response(
* response=404,
* description="not found"
* ),
* )
*/
public function getAllCountries(){
return serviceApi("countries");
}
Ensuite régénérons la documentation :
$ php artisan l5-swagger:generate
Vous devriez voir quelque choses comme ci:
Cet EndPoint renvoie la liste des pays touché par la Covid19
Consommons et documentons les deux(2) autres endPoints que reçoivent des paths variables.
Notre Controller devrait ressembler a ceci:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ApiController extends Controller
{
/**
* @OA\Get(
* path="/v1/countries",
* operationId="getAllCountrie",
* tags={"Tests"},
* summary="Get List Of Countries",
* description="Returns all countries and associated provinces. The country_slug variable is used for country specific data",
* @OA\Response(
* response=200,
* description="Successful operation",
* @OA\MediaType(
* mediaType="application/json",
* )
* ),
* @OA\Response(
* response=401,
* description="Unauthenticated",
* ),
* @OA\Response(
* response=403,
* description="Forbidden"
* ),
* @OA\Response(
* response=400,
* description="Bad Request"
* ),
* @OA\Response(
* response=404,
* description="not found"
* ),
* )
*/
public function getAllCountries(){
return serviceApi("countries");
//return "Hello Swagger";
}
/**
* @OA\Get(
* path="/v1/countries/{country}",
* operationId="getCountryConvidInfos",
* tags={"Tests"},
* summary="Get List Of Cases Per Country Per Province By Case Type From The First Recorded Case",
* description="Returns all cases by case type for a country from the first recorded case. Country must be the country_slug from /countries. Cases must be one of: confirmed, recovered, deaths",
*@OA\Parameter(
* name="country",
* in="path",
* required=true,
* @OA\Schema(
* type="string"
* )
* ),
* @OA\Response(
* response=200,
* description="Successful operation",
* @OA\MediaType(
* mediaType="application/json",
* )
* ),
* @OA\Response(
* response=401,
* description="Unauthenticated",
* ),
* @OA\Response(
* response=403,
* description="Forbidden"
* ),
* @OA\Response(
* response=400,
* description="Bad Request"
* ),
* @OA\Response(
* response=404,
* description="not found"
* ),
* )
*/
public function getCovid19InfosByCountries($country){
$endPoint="dayone/country/$country";
return serviceApi($endPoint);
}
/**
* @OA\Get(
* path="/v1/amount/{country}",
* operationId="getCountryConvidInfos",
* tags={"Tests"},
* summary="Get List Of Cases Per Country Per Province By Case Type From The First Recorded Case",
* description="Returns all cases by case type for a country from the first recorded case. Country must be the country_slug from /countries. Cases must be one of: confirmed, recovered, deaths",
*@OA\Parameter(
* name="country",
* in="path",
* required=true,
* @OA\Schema(
* type="string"
* )
* ),
* @OA\Response(
* response=200,
* description="Successful operation",
* @OA\MediaType(
* mediaType="application/json",
* )
* ),
* @OA\Response(
* response=401,
* description="Unauthenticated",
* ),
* @OA\Response(
* response=403,
* description="Forbidden"
* ),
* @OA\Response(
* response=400,
* description="Bad Request"
* ),
* @OA\Response(
* response=404,
* description="not found"
* ),
* )
*/
public function getTotalByCountries($country){
$endPoint="total/dayone/country/$country";
return serviceApi($endPoint);
}
}
Taper cette commande pour regénérer la doc:
$ php artisan l5-swagger:generate
Tu peux ensuite consulter ta doc et tu connais déjà le lien…
C'EST LA FIN
Merci a toi qui a lue cet article et a très bien bientôt.