Configurer votre Contrôleur afin de mettre en place une API REST

Robustesse de votre API REST Laravel 5.5

L’objectif de cette suite de tutoriels sur Laravel 5.5 est de permettre au développeur Web de déployer une API REST de qualité sur le Net.

La quatrième étape consiste à augmenter la robustesse des actions de vos contrôleurs en ajoutant une couche de validation. Cette étape est essentielle afin de garantir le format des données provenant des clients.

Récit utilisateur proposé

  • En tant que développeur, j’aimerais une ressource measure robuste et bien testée.
    • Routes reliées :
      • GET /api/measures/ 200
      • POST /api/measures/ 201 et 422
      • GET /api/measures/{measure} 200 et 404
      • PUT /api/measures/{measure} 200 et 422
      • DELETE /api/measures/{measure} 200 et 404
  • Signification des codes de retour HTTP :
    • 200 : Succès
    • 404 : Non trouvé
    • 422 : Erreur de validation

Plan de match pour ce tutoriel

  1. Implémenter toutes les actions du contrôleur (store, index, show, update et destroy) et écrire les tests associés.
  2. Créer les classes FormRequest afin de valider les requêtes du client et retourner les messages d’erreur appropriés.

N’oubliez pas qu’il me fera plaisir de répondre à vos questions en bas de page. Bon succès!

Si vous avez de la difficulté à implémenter les méthodes store, index, show, update et destroy. Veuillez lire l’Annexe 1 : Code du contrôleur avec robustesse.

FormRequest

Créer une classe FormRequest qui validera les données envoyées par le client :

$ php artisan make:request MeasurePostRequest

# Voir le dossier AppHttpRequest

La méthode authorize doit retourner true.

La méthode rules doit contenir un tableau des règles de validation reliées à votre modèle Measure.

Lire la documentation sur les rèles de validations avec Laravel 5.5.

Règles de validation proposées

  • Les champs value et description sont obligatoires.
  • Le champ value est un entier et description une chaîne.

Modifier votre contrôleur

Modifier l’action store de contrôleur afin d’y ajouter le nouveau FormRequest.

public function store(MeasurePostRequest $request)

Avec le nouveau FormRequest, les règles de validation seront automatiquement appliquées. Les messages appropriés seront retournés au client.

Vous pouvez tester avec Postman. N’oubliez pas de définir les en-têtes suivantes :

  • Accept : application/json
  • Content-Type : application/json

Prendre une pause

La position assise est très dommageable pour la santé. De plus, regarder un écran pendant plus de 20 minutes est aussi mauvais.

Prenez le temps de vous lever et de vous étirer durant 45 secondes.
Prenez aussi conscience de la position de votre corps lorsque vous travaillez.

Maintenant, vous devrez écrire les tests.

Tester la robustesse

Tester le bon fonctionnement et la robustesse de vos actions. Afin de bien tester, vous devez considérer le code de statut (ex : 404, 422, 403, 500, 200, 201, …) retourné par l’API ainsi que les données JSON.

Lors du troisième tutoriel, des données de tests (seed) ont été créées, ces données devraient être utilisées dans vos tests.

Cas de tests à considérer

  • POST valide
  • Requête POST sans données JSON
  • Requête POST sans l’attribut description
  • Requête POST sans l’attribut value
  • Requête POST avec l’attribut value en chaîne de caractères
  • GET, PUT, POST, …

Créer le fichier de tests

$ php artisan make:test MeasureTest

Implémenter les tests nécessaires afin de garantir la qualité et la robustesse.

Voici un peu de code pour vous aider :

public function testPostMeasure()
{
$response = $this->post(‘/api/measures’,
[‘value’=> ‘3’, ‘description’=>’co2’],
[‘Accept’=> ‘application/json’]);

  $response->assertJsonFragment([‘value’=>’3’]);
$response->assertStatus(200);
}

Ajouter un test afin de vérifier la méthode POST lorsque le JSON est incomplet :

public function testPostMeasureWithoutValueTest()
{
$response = $this->post(‘/api/measures’,
[‘description’=>’co2’],
[‘Accept’=> ‘application/json’]);

  $response->assertJsonFragment(
[« value »=>[« The value field is   required. »]]);
$response->assertStatus(422);
}

La méthode assertJsonFragment permet de valider un fragment de la réponse.

$response->assertJsonFragment([‘value’=>’3’]);

La méthode assertStatus permet de valider le code de statut retourné.

$response->assertStatus(422);

Lancer les tests :

$ vendor/phpunit/phpunit/phpunit

Références sur les tests :

Réusinage du code

Afin de retirer les routes create et edit, modifier le fichier des routes (Routesapi.php). Ces routes ne sont pas utiles pour une API REST.

Route::resource(‘measures’, ‘MeasureController’);

devient

Route::apiResource(‘measures’, ‘MeasureController’);

$ php artisan route:list

Les routes create et edit seront retirés.

Supprimer les méthodes inutiles du contrôleur.

Relancer les tests :

$ vendor/phpunit/phpunit/phpunit

Pousser sur GitLab

Finalement, publier votre travail sur GitLab avec la suite de commande suivante :

$ git add .
$ git commit -m « MeasureController CRUD tested »
$ git push

Implicit Binding

Le binding implicite permet de simplifier le code de votre contrôleur en demandant à Laravel de charger automatiquement le modèle spécifié par un id dans la route. Donc plutôt que d’avoir le code suivant, avec le paramètre $id :

public function show($id)
{
$measure = Measure::findOrFail($id);
return new MeasureResource($measure);
}

Il sera possible de réusiner le code de cette manière :

public function show(Measure $measure)
{
return $measure;
}

Attention, le nom de la variable en gras $measure, doit correspondre au nom entre accolades affiché dans la route.

$ php artisan route:list

GET | HEAD /api/measures/{measure}

Annexe 1 : Code du contrôleur StationController

use AppStation;
use AppHttpResourcesStation as StationResource;
use IlluminateHttpRequest;
use AppHttpRequestsStationRequest;

class StationController extends Controller
{

/**
* Display a listing of the resource.
*
* @return IlluminateHttpResponse
*/
public function index()
{

$stations = Station::paginate(5);
return StationResource::collection($stations);

}

/**
* Store a newly created resource in storage.
*
* @param AppHttpRequestsStationRequest $request
* @return IlluminateHttpResponse
*/
public function store(StationRequest $request)
{

// Si MassAssignmentException
// Ajouter au modèle
// protected $fillable = [‘description’, ‘lat’, ‘long’];
$station = new Station($request->all());
$station->save();

// Alternative
// $station = new Station();
// $station->description = $request->input(‘description’);
// $station->lat = $request->input(‘lat’);
// $station->long = $request->input(‘long’);

if($station->save()) {
return new StationResource($station);
}

}

/**
* Display the specified resource.
*
* @param AppStation $station
* @return IlluminateHttpResponse
*/
public function show(Station $station)
{

return new StationResource($station);

}

/**
* Update the specified resource in storage.
*
* @param IlluminateHttpRequest $request
* @param AppStation $station
* @return IlluminateHttpResponse
*/
public function update(StationRequest $request, Station $station)
{

$station = Station::findOrFail($station->id);
$station->description = $request->input(‘description’);
$station->lat = $request->input(‘lat’);
$station->long = $request->input(‘long’);
$station->save();

return new StationResource($station);

}

/**
* Remove the specified resource from storage.
*
* @param AppStation $station
* @return IlluminateHttpResponse
*/
public function destroy(Station $station)
{

if($station->delete()) {
return new StationResource($station);
}

}

}

Bravo!

Bravo, votre environnement de développement avec Homestead, Vagrant, PHP, MySQL est fonctionnel.

Configurons une application qui utilise le cadriciel Laravel.

Références et lectures

  • https://www.getpostman.com/
  • https://github.com/symfony/symfony/
  • https://vagrantup.com/downloads.html

Pour terminer en beauté, merci de partager!


Comments

comments