Aller au contenu
M07 · D. Découvrir l'architecture MVC

Les services web : SOAP et REST, écrire une API JSON

Ce qu'est un service web, la comparaison SOAP / REST, les principes de REST (ressources, verbes HTTP, codes de statut, sans état), le format JSON avec json_encode et json_decode, l'écriture d'une API produits en PHP et son appel depuis JavaScript avec fetch.

1Situer

Souk Atlas veut une application mobile, et un transporteur de Casablanca veut consulter les commandes à livrer depuis son propre logiciel. Ni l'un ni l'autre n'a besoin de pages HTML : ils veulent les données. Un service web les leur fournit dans un format que n'importe quel programme sait lire.

2Comprendre

Une API REST : des données au lieu de pages
Applimobile api/produits.php GET ?id=9 {"nom":"Plateau en cuivre","prix":210} 200 OK {"id":9,"nom":"Tapis berbère", "prix":"1200.00","stock":3}

L'application mobile demande GET /api/produits.php?id=9. Elle veut des données, pas une page HTML.

1 / 5

Qu’est-ce qu’un service web ?

Une API (Application Programming Interface) est l’ensemble des opérations qu’un programme met à la disposition des autres. Quand ces opérations passent par le web, on parle d’API web ou de service web. Deux grands styles existent.

SOAP et REST

SOAPREST
Natureprotocole normaliséstyle d’architecture
FormatXML uniquementJSON le plus souvent (aussi XML, CSV…)
ContratWSDL obligatoirelibre (documentation, souvent OpenAPI)
Verbes HTTPpresque toujours POSTGET, POST, PUT, PATCH, DELETE
Erreursélément <soap:Fault>codes de statut HTTP
Poids des messageslourd (enveloppe XML)léger
Usages typiquesbanque, assurance, administrations, systèmes anciensapplications mobiles, sites JavaScript, API publiques

Verbes et codes de statut

VerbeSur /api/produits.phpSur /api/produits.php?id=9
GETliste des produitsle produit 9
POSTcréer un produit—
PUT / PATCH—remplacer / modifier le produit 9
DELETE—supprimer le produit 9

Les codes les plus utilisés : 200 OK, 201 Created (après un POST), 204 No Content (après un DELETE), 400 Bad Request (JSON illisible), 401 Unauthorized (pas identifié), 403 Forbidden (pas le droit), 404 Not Found, 405 Method Not Allowed, 422 Unprocessable Content (données invalides), 500 erreur du serveur.

JSON en PHP

$p = ['id' => 9, 'nom' => 'Tapis berbère', 'prix' => 1200.0, 'en_stock' => true];

echo json_encode($p);
// {"id":9,"nom":"Tapis berb\u00e8re","prix":1200,"en_stock":true}

echo json_encode($p, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
// accents gardés, une clé par ligne

$tab = json_decode('{"nom":"Savon noir","prix":30}', true);   // tableau associatif
echo $tab['nom'];                                               // Savon noir

Un tableau indexé ([0 => ..., 1 => ...]) devient une liste JSON [...], un tableau associatif devient un objet {...}. Sans le second argument true, json_decode renvoie un objet stdClass ($obj->nom).

Écrire l’API

Le squelette d’une API en PHP natif tient en quelques étapes :

  1. envoyer l’en-tête Content-Type: application/json; charset=utf-8 ;
  2. lire $_SERVER['REQUEST_METHOD'] et l’identifiant éventuel ;
  3. pour POST et PUT, lire le corps avec json_decode(file_get_contents('php://input'), true) ;
  4. valider, appeler la base avec des requêtes préparées (ou un modèle de la leçon D.1) ;
  5. répondre avec http_response_code() et json_encode().

Appeler l’API depuis JavaScript

C’est le lien avec le module de programmation JavaScript : la page HTML est chargée une fois, puis fetch demande les données à l’API et met la page à jour sans la recharger.

// lire
const produits = await fetch('api/produits.php').then((r) => r.json());

// créer
const r = await fetch('api/produits.php', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ nom: 'Lanterne', categorie_id: 1, prix: 260 }),
});
if (r.status === 201) console.log('créé', await r.json());
Exemple simple

Le comptoir de la grande surface

Au comptoir, il y a des gestes standards : consulter un article, en commander un, modifier ou annuler une commande. N'importe quel client sait s'en servir sans connaître l'entrepôt. Une API REST propose ces gestes (GET, POST, PUT, DELETE) sur des ressources.

Exemple simple

Le formulaire administratif officiel

Certaines démarches exigent un formulaire très détaillé, toujours le même, avec tampons et rubriques obligatoires. C'est l'esprit de SOAP : un contrat strict (WSDL) et des messages XML complets, lourds mais très encadrés.

3Manipuler

Terminez l'API des produits : elle répond en JSON, avec le bon code de statut. La page index.html l'utilise avec fetch pour afficher le catalogue.
Pas à pas dans le lab ↗ Cliquez sur Exécuter : PHP 8.3 démarre dans votre navigateur (environ 5 Mo à télécharger, une seule fois).

La page s'affichera ici.

Le navigateur demandera /api/produits.php au serveur, qui exécutera le PHP et renverra du HTML.

Entre le navigateur et le serveur aucun échange pour l'instant

Consignes 0 / 4

  1. GET api/produits.php?id=9 renvoie le Tapis berbère en JSON
  2. GET api/produits.php?id=99 répond 404 avec un message d'erreur
  3. Un POST JSON complet crée le produit et répond 201
  4. Un POST sans prix répond 422 et n'ajoute rien

4Pratiquer

Exercice 1 · Modifier et supprimer

Complétez l'API avec PUT api/produits.php?id=9 (mise à jour du prix et du stock à partir du JSON reçu) et DELETE api/produits.php?id=9. Répondez 204 sans contenu après une suppression réussie, 404 si le produit n'existe pas.

Voir le corrigé
<?php
if ($methode === 'PUT' && $id) {
    $d = json_decode(file_get_contents('php://input'), true) ?? [];
    $req = $pdo->prepare('UPDATE produits SET prix = :prix, stock = :stock WHERE id = :id');
    $req->execute(['prix' => $d['prix'] ?? 0, 'stock' => $d['stock'] ?? 0, 'id' => $id]);
    $req = $pdo->prepare('SELECT id, nom, prix, stock FROM produits WHERE id = ?');
    $req->execute([$id]);
    $p = $req->fetch();
    $p ? repondre(200, $p) : repondre(404, ['erreur' => 'Produit introuvable']);
}
if ($methode === 'DELETE' && $id) {
    $req = $pdo->prepare('DELETE FROM produits WHERE id = ?');
    $req->execute([$id]);
    if ($req->rowCount() === 0) repondre(404, ['erreur' => 'Produit introuvable']);
    http_response_code(204);
    exit;
}

Exercice 2 · Consommer une API depuis PHP

Un autre script PHP doit lire le produit n° 9 de l'API et afficher son nom. Utilisez file_get_contents sur l'URL de l'API, puis json_decode.

Voir le corrigé
<?php
$json = file_get_contents('http://localhost/api/produits.php?id=9');
$produit = json_decode($json, true);   // true : tableau associatif plutôt qu'objet
if (json_last_error() !== JSON_ERROR_NONE) {
    exit('Réponse illisible');
}
echo htmlspecialchars($produit['nom']);   // Tapis berbère

Exercice 3 · SOAP ou REST ?

Pour chaque situation, dites quel style vous choisiriez et pourquoi : (a) une application mobile qui affiche le catalogue ; (b) la connexion à un service bancaire existant qui fournit un fichier WSDL ; (c) un site JavaScript qui met à jour le panier sans recharger la page.

Voir le corrigé
(a) REST + JSON : léger, lisible, facile à consommer depuis le mobile, et les GET se mettent en cache.
(b) SOAP : le service impose déjà un contrat WSDL ; la classe SoapClient de PHP génère les appels à partir de ce contrat.
(c) REST + JSON : fetch() en JavaScript lit directement le JSON, sans enveloppe XML à analyser.

5Vérifier

1. Dans une API REST, quel verbe HTTP sert à créer une ressource ?
2. Quel code de statut indique qu'une ressource a été créée ?
3. Comment lire en PHP le JSON envoyé dans le corps d'une requête POST ?