Vous êtes sur la page 1sur 22

Web service RESTful

Un web service basé sur une architecture REST est un service web RESTful.
Toute application web qui retourne un format JSON n’est pas automatiquement
un service web RESTful et un web service RESTful ne retourne pas que du JSON.
Ce type de service web est multiformat.
Un service web est un logiciel conçue pour assurer l’interopérabilité entre deux
ou plusieurs système dans un réseau informatique (Haafiz W. A., 2017).
Pourquoi un service web ?
Selon la définition précédente, un service web est souvent utilisé pour assurer la
communication entre différents systèmes et terminaux. Dans ce cours nous
utiliserons un service web fournissant un interface par lequel une application
mobile ou web pourra communiquer avec un serveur pour obtenir ou stocker des
données. Ceci permet de séparer la couche client d’une application de la couche
logique du serveur. De nos jours les application SAPs (Single Page Applications)
et mobiles doivent être séparées des serveurs avec lesquels ces applications sont
en interaction via les services web qui assurent l’échange. Il faut savoir que les
service web ne sont pas destinés à assurer les échanges uniquement entre
applications clientes et serveurs mais aussi entre serveurs.
REST architecture
REST (Representational State Transfer) est une architecture fondée par Roy
Fielding en 2000. C’est un style d’architecture permettant de construire des
applications (Web, Intranet, Web Service). Il s’agit d’un ensemble de conventions
et de bonnes pratiques à respecter et non d’une technologie à part entière.
L’architecture REST utilise les spécifications originelles du protocole HTTP,
plutôt que de réinventer une surcouche (comme le font SOAP ou XML-RPC par
exemple). Un système RESTful doit se conformer à ces six contraints.
Interface uniforme
La première contrainte de l’architecture REST que nous allons examiner est celle
de l’interface uniforme. Dans une approche RESTful, il est utile de conceptualiser
et de classer les services individuels comme des ressources d’application qui
exposent leur propre interface client. Il est important que ces ressources soient
suffisamment petites en matière de portée et de volume de données pour
qu’une seule interface puisse aisément les gérer. Enfin, REST exige que les
mécanismes d’interface que ces ressources emploient, pour exposer leurs
capacités, se comportent de manière cohérente avec toutes les autres interfaces
qui exhibent des services connexes.
Il s’agit d’une contrainte assez facile à respecter, à condition que les architectes
fassent l’effort de considérer ces ressources comme des « noms » – en d’autres
termes, des entités uniques qui acceptent les entrées et interprètent les appels sous
la forme d’instructions procédurales pour une certaine opération (qui pourraient
être traitées comme des « verbes »). Il s’agit d’un principe fondamental de la
programmation orientée objet. Si l’on simplifie, les services sont des objets qui
prennent des commandes. Pour s’en souvenir, il suffit de penser à l’envoi
d’actions à des objets, et non d’objets à des actions.
Notez qu’il est également important pour les architectes de rester cohérents en
matière de définition des ressources et de conception des API, afin que les
ressources ne s’alignent pas par erreur et ne partagent pas de données avec la
mauvaise API ou interface client.
Modèle client-serveur (séparation de responsabilité)
La prochaine contrainte à aborder est le modèle client-serveur, qui exige que le
couplage entre une ressource RESTful et les API associées n’existe que dans
l’interface côté client. Ces ressources sont libres d’évoluer indépendamment, mais
l’interface doit rester intacte.
Ce couplage léger permet de réduire les relations de dépendance mal gérées qui
provoquent des pannes et compliquent les processus de mise à jour, ce qui est
essentiel lorsque les développeurs créent fréquemment des ressources et des
clients de manière isolée. Il est également plus facile pour les équipes logicielles
de collaborer au niveau où le développement back-end rencontre la conception
front-end, car il y a moins de risque que les programmeurs effectuent une
modification qui casse ou altère soudainement la fonctionnalité de l'interface.
Stateless
Nous allons maintenant examiner la contrainte Stateless. Le comportement
stateless est une caractéristique particulièrement critique des architectures basées
sur REST. Cela signifie que le serveur qui fournit les ressources applicatives
ne stocke pas d’informations entre les requêtes et n’impose pas de séquence
de traitement pour les appels et les requêtes. Le résultat de chaque requête doit
être hiérarchisé uniquement en fonction de son contenu et de l’opération spécifiée
– et non en fonction de comportements antérieurs concernant des séquences
d’événements ou des ordres d’opérations.
Cette propriété est la clé pour l’évolutivité et la résilience des services, car elle
signifie que toute instance d’une ressource répond à une requête de la même
manière, indépendamment des calendriers de traitement généraux. Cependant, la
conception stateless est compliquée à réaliser, en particulier lorsque les requêtes
fréquentes contiennent des quantités importantes de données liées à l’état. La
façon la plus simple de l’aborder, si possible, est d’éviter complètement de stocker
les données internes entre les requêtes de ressources, y compris la séquence
spécifique des appels et des requêtes.
Mise en cache
La contrainte qui semble dérouter le plus les architectes est l’exigence de mise en
cache. Essentiellement, une architecture est antémémorisable (cachable) si la
réponse d’un serveur peut être stockée dans un dépôt intermédiaire et, idéalement,
abstrait. En cas de besoin, ce dépôt peut offrir ces réponses en cache pour un point
d’emplacement de réutilisation et garantir –pour une période déterminée, au
moins – que le comportement de ces réponses ne changera pas.
Il n’est pas nécessaire que tout puisse être mis en cache pour satisfaire à cette
contrainte, mais chaque réponse qui peut l’être facilement et à un coût raisonnable
doit être identifiée. De plus, le cache doit être capable de servir de nouvelles
requêtes chaque fois qu’il peut gérer en toute sécurité des charges de travail
lourdes à la place du serveur.
Si les réponses du serveur et les ressources qu’il fournit ne font pas l’objet de
mises à jour programmées ou de changements de fonctionnalités, il est prudent
d’inclure cette information dans les réponses du serveur au client. De cette façon,
les systèmes d’application aux abois peuvent s’appuyer sur le cache en cas de
retard dans les réponses ou de panne du serveur.
Modèle de système multicouche
La cinquième contrainte de l’architecture REST est le modèle de système en
couches, selon lequel une application doit pouvoir définir les ressources en les
affectant à des couches de fonctionnalité, chaque couche correspondant à une
capacité de service unique et partagée. Dans certains cas, ces capacités peuvent
être quelque chose de simple, par exemple des activités de répartition de charge.
Dans d’autres cas, la strate peut abriter un processus plus complexe qui exige
plusieurs serveurs et éléments logiciels, comme le traitement des données
volumineuses.
Le code à la demande
Le code à la demande est la dernière contrainte, et la seule parfois considérée
comme facultative. Cette pratique stipule que, lorsqu’elles répondent à des
requêtes, les ressources RESTful doivent être prêtes à fournir du code qui sera
interprété côté client plutôt que côté serveur (ou quelque part entre les deux). Le
fait de pousser du code côté client permet de distribuer le travail lorsque
l’exécution côté serveur risque de provoquer des défaillances ou des problèmes
de performance.
Pour mettre en pratique ce modèle, il faut connaître un peu les capacités
d’exécution du code des clients qui accèdent à une ressource. Pour ce faire, le
serveur doit identifier les capacités spécifiques du client afin de s’assurer que le
code s’exécutera réellement comme prévu de ce côté-là. Il utilise généralement
un langage de programmation universel que la plupart des composants applicatifs
associés prennent en charge et comprennent lors d’un échange de code.
Comme c’est le cas pour la contrainte de mise en cache évoquée précédemment,
il n’est pas nécessaire de segmenter chaque service RESTful en sa propre strate.
Au lieu de cela, il suffit de se concentrer sur la capacité à prendre pleinement en
charge le modèle en couches lorsque cela est requis. Heureusement, la mise en
œuvre d’un tel modèle est relativement simple, à condition que l’architecture soit
conçue pour le gérer.
Application avec Laravel
Sous Windows Installation de Laragon
Laragon est une application bureautique similaire à WampServer ou XAMPP,
mais il présente l’avantage d’être spécialement conçu pour Laravel. Cela permet
de démarrer rapidement sur un environnement adapté au framework.
Télécharger sur https://laragon.org/download/
Le lien suivant https://laragon.org/docs/install.html vous permet d’installer
Largon.
Création d’un API
Notre API est un projet Laravel donc nous allons lancer Laragon pour créer un
projet Laravel comme suit :
Renseigner le nom de votre application et cliquer sur ok. Laissez Laragon installer les différents
packages et composants nécessaire. A la fin on obtiendra. Le lien http://cours.test permet de
tester notre projet.

La création de ce projet peut se faire en lançan la commande suivante sur mon terminal :

cd C:\laragon\www
composer create-project laravel/laravel cours --prefer-dist

si le projet marche, avec le lien http://cours.test on aura la page suivante :


Organisation de laravel
Une fois laravel installé, vous avez une organisation de dossier comme le montre la figure
suivante :

- Le dossier app qui contient les éléments essentielles de l’application. Il contient des
sous dossiers comme :

 Consol : Pour toutes les commandes en mode console,


 Exceptions : pour gérer les erreurs d’exécution,
 Http : tout ce qui concerne la communication : contrôleurs, middlewares (il y a
7 middlewares de base qui servent à filtrer les requêtes HTTP) et le kernel,
 Providers : tous les fournisseurs de services (providers), il y en a déjà 5 au
départ. Les providers servent à initialiser les composants.
 Models : le dossier des modèles avec déjà un présent qui concerne les
utilisateurs.
- bootstrap : scripts d’initialisation de Laravel pour le chargement automatique des
classes, la fixation de l’environnement et des chemins, et pour le démarrage de
l’application,
- public : tout ce qui doit apparaître dans le dossier public du site : images, CSS, scripts…
- config : toutes les configurations : application, authentification, cache, base de données,
espaces de noms, emails, systèmes de fichier, session…
- database : migrations et populations,
- resources : vues, fichiers de langage et assets (par exemple les fichiers Sass),
- routes : la gestion des urls d’entrée de l’application,
- storage : données temporaires de l’application : vues compilées, caches, clés de
session…
- tests : fichiers de tests unitaires,
- vendor : tous les composants de Laravel et de ses dépendances (créé par composer).
Il y a aussi des fichiers racines comme le montre la figure suivante :

A Partir de l’image, nous allons détailler les fichiers importants :


artisan : outil en ligne de Laravel pour des tâches de gestion,
composer.json : fichier de référence de composer,
package.json : fichier de référence de npm (Node package Manager) pour les assets,
phpunit.xml : fichier de configuration de phpunit (pour les tests unitaires),
.env : fichier pour spécifier l’environnement d’exécution.
Serveur de laravel
Laravel fournit un microserveur web qu’on peut lancer directement avec la commande php
artisan serve dans un terminal depuis la racine d’une application Laravel. Cette commande
démarre un serveur PHP sur le port 8000 directement utilisable pour faire quelque tests. L’url
utilisé est alors : http://127.0.0.1:8000/
Création de la base de données
Créons la base de données blog avec MySQL en utilisant phpMyAdmin, un client à MySQL ou
la commande create DATABASE blogs ; depuis le terminal. La base de données contient trois
tables comme le montre le modèle suivant :

Nous n’allons pas implémenter ce modèle directement par des scripts SQL, mais nous allons
utiliser une commande pour créer des fichiers de migration qui vont générer la base de données.
Avant cela nous allons dans le fichier .env pour configurer la connexion à la base de données
comme suit :
DB_DATABASE =blogs ;
DB_USERNAME = root ;
DB_PASSWORD = ******
Pour le mot de passe, mettez vos mots de passes respectives de vos serveurs DB MySql.
Création des fichiers de migrations
Pour créer le fichier de migration d’une table, il faut écrire :
php artisan make :migration create_[nom de la table]_table
Une fois la commande exécutée on obtient le fichier comme suit :
Created Migration : date_heure_create_[nom de la table]_table
Les fichiers de migration seront dans le sous dossiers migrations du dossiers principale
database.
Exemple :
Pour créer le fichier de migration pour la table posts on écrit :
php artisan make :migration create_posts_table et on voit sur le terminal apparaître
l’instruction suivante : Created Migration: 2022_12_20_100030_create_posts_table

La commande php artisan migrate permet d’exécuter le fichier de migration non encore
exécuté. Dans notre exemple, cette exécution permet de créer la table posts au niveau de la base
de données. Avant d’exécuter la commande, cliquez sur le fichier de migration de posts pour
compléter les propriétés comme le montre la figure suivante :
On constate que cette classe hérite de la classe Migration. La fonction up() permet de créer la
table au niveau de la base de données grâce à la méthode Schema::create et la fonction down()
permet de supprimer la table via la méthode Schema::dropIfExists() ;. Pour plus d’information
sur les commandes Migration allez sur le lien https://laravel.com/docs/9.x/migrations. Faites
la même chose pour les autres tables.
Création des contrôleurs
Dans le modèle MVC, le contrôleur contient la logique concernant les actions effectuées par
l’utilisateur. En pratique, dans une application laravel, l’utilisation de contrôleur permet de
libérer les routes du code qu’elles contiennent dans leurs fonctions de rappel. Un contrôleur est
matérialisé par une classe et chacune de ses méthodes représente une action. Une action
correspond généralement à une route.
Il existe un fichier des routes routes/web.php qui fait le lien entre les URI de l’API et les
actions à effectuer pour chacune de ces URI. (Exemple d’URI : /{ressource}/{ressource_id}).
Avant de créer les routes (endpoint en Anglais), nous d’abord voir comment créer un contrôleur.
la commande php artisan make:controller sera utilisée pour générer les contrôleurs.
Pour générer le contrôleur PostController, on tape :
php artisan make : controller API/PostController - -model=Post - -api
Les options :
 - -api permet de retirer les méthodes create et edit du contrôleur puisqu'elles ne sont pas
utiles pour une API. Il va nous rester index, store, show, update et destroy.
 - -model=Post permet d'importer et d'injecter le modèle /app/Models/Post.php aux
méthodes show, update et destroy du contrôleur
Rappelons qu’il existe 7 méthodes qu’on pourrait obtenir si on remplaçait l’option - - api par -
- resource au niveau de la commande de création du contrôleur. Ces 7 méthodes sont :
- Index() : est utilisée pour afficher une liste d’information (Post).
- Create(): affichera le formulaire ou la vue pour créer un Post.
- Store(): est utilisée pour insérer un Post dans la base de données. Remarque: la méthode
create() submit les données du formulaire à la méthode store().
- Show(): affichera un Post spécifié.
- Edit(): affichera le formulaire pour éditer un Post. Le formulaire sera rempli avec les
données de la voiture existante.
- Update(): La méthode update() est utilisée pour mettre à jour un Post dans la base de
données. Remarque: la méthode edit() submit les données du formulaire à la méthode
update().
- Destroy(): est utilisée pour supprimer un Post specifique spécifié.
Une fois la commande exécutée, une classe contrôleur est créée dans le répertoire controllers
comme le montre la figure suivante :

Le code de la classe se présente comme suit :


class PostController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
//
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//
}

/**
* Display the specified resource.
*
* @param \App\Models\Post $post
* @return \Illuminate\Http\Response
*/
public function show(Post $post)
{
//
}

/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param \App\Models\Post $post
* @return \Illuminate\Http\Response
*/
public function update(Request $request, Post $post)
{
//
}

/**
* Remove the specified resource from storage.
*
* @param \App\Models\Post $post
* @return \Illuminate\Http\Response
*/
public function destroy(Post $post)
{
//
}
}
On constate que la classe contient les méthodes :
- index()
- store()
- show()
- update()
- destroy()
Création de routes
Pour une API, les routes sont définies dans le répertoire routes/api.php de laravel. La méthode
Route ::apiRessource() permet de définir la route pour les ressources de Post. Ainsi on peut
écrir au niveau du terminal : Route ::apiRessource(‘post’, PostConroller ::class). La
commande php artisan route : List permet d’afficher les routes créées pour consommer un
API. La figure ci-dessous montre la liste des routes créées pour le contrôleur Post.

La différence entre Route ::apiRessource() et Route ::Ressource() est au niveau des


itinéraires créés. Route ::apiRessource() crée les routes pour index, store, show, update et
destroy.
Maintenant nous avons besoin d’ajouter du code au niveau de chaque action du contrôleur Post
afin de pouvoir interagir avec la base de données. Mais pour que l’interaction soit possible, il
faut qu’on crée d’abord le modèle approprié.
Eloquent ORM (couche modèle)
Eloquent est un ORM de Laravel et Lumen. Il est responsable des opérations liées à la base de
données ainsi que des relations entre les bases de données. L’ORM (Object Relational
Mapping) fait essentiellement correspondre des objets avec des relations (tables) dans la base
de données. En plus de cela, sur la base de la relation, vous pouvez obtenir des données d'une
table à partir d'une autre table sans aller dans les détails de bas niveau. Cela permet non
seulement de gagner du temps mais aussi de garder notre code plus propre.
Création de modèle
Pour créer un modèle, nous allons utiliser la commande : php artisan make : model
nom_model. Dans notre cas, nous allons créer les modèles selon le diagramme de classe
précédemment illustré. Le modèle User est créé par défaut avec laravel. Le modèle Post est déjà
créé lors de la création du contrôleur PostController nous ne ferons que le modifier. Ci-joint
la classe du modèle de Post.
La fonction user() représente la relation existant entre la table users et posts de la base de
données. Un post appartient à un utilisateur. Pour la fonction comments(), un post a plusieurs
comments. Les figures suivantes correspond au modèle de Comment.
Générer les données fictives dans la base de données pour les tests
Il existe deux moyens pour générer ou fabriquer les données de test dans notre base de données.
Laravel permet d’utiliser les classes Seeders et aux Factories pour cette opération de
fabrication de données.
Les seeders
Il est possible de n’utiliser que les Seeders pour peupler notre base de données de manière très
basique. Mais pour mieux gérer les relations entre les tables d’une base de données pendant la
fabrication des données, les Factories seront utilisés. Pour créer un nouveau seeder pour notre
table posts lancez la commande :
php artisan make:seeder PostSeeder
on obtient la classe suivante :
Ici nous avons crée un seeder spécialement pour la table “posts” même si nous aurions pu écrire
le code que nous devrons lancer dans le fichier de base DatabaseSeeder.php. Nous préférons
être bien organisé dès le début. Comme la table posts contient la clé étrangère user_id, il faut
d’abord créer les utilisateurs avant de créer les posts. Ainsi avec la même commande, on créé
le UserSeeder. On obtient alors :

Mais pour que notre seeder PostSeeder et UserSeeder s’exécutent nous devons utiliser la
méthode call dans la méthode run() de notre Class DatabaseSeeder comme ceci :
Retournons un peut en arrière pour définir les seeder comme suit :
PostSeeder
Nous allons maintenant lancer nos seeders. Mais avant nous allons vider la base de données en
lançant la commande : php artisan migrate:fresh
La commande php artisan db:seed permet de lancer les seeders.
On constate les seeders permettent de créer des données enregistrement par enregistrement.
Cette limite est aussi relevée par les factories.
Les Factories
Les Factories sont là pour nous permettre de créer des enregistrements en quantité et d’établir
facilement diverses relations entre nos tables. Par défaut on a UserFactory créé avec Laravel.
Nous allons créer maintenant PostFactory en utilisant la commande suivante :
php artisan make:factory PostFactory
on obtient :

Maintenant que nous avons créer nos factories, retournons dans le fichier PostSeeder.php et
DatabaseSeeder.php
PostSeeder

Ici nous somme entrain de créer 10 enregistrements dans la table post.


DatabaseSeeder

Pour lancer la création des enregistrements dans les table users et posts en utilisant la
commande : php artisan migrate:fresh --seed
Implémentation des actions des contrôleurs
Contrôleur Post
Action index()

Vous aimerez peut-être aussi