app | ||
bootstrap | ||
config | ||
database | ||
public | ||
resources | ||
routes | ||
storage | ||
tests | ||
.editorconfig | ||
.env.example | ||
.gitattributes | ||
.gitignore | ||
.styleci.yml | ||
artisan | ||
composer.json | ||
composer.lock | ||
package.json | ||
phpunit.xml | ||
README.md | ||
server.php | ||
webpack.mix.js |
Test Technique HelloCSE
Prérequis
Si PHP et/ou Composer sont manquants, installer Laravel Herd
PHP 8.1 minimum est requis. : utilisation d'opérateur de décomposition sur tableau associatif
Installation
-
Télécharger/Cloner le dépôt
-
Configurer le fichier .env
APP_DEV=true # doit être à false si en production
DB_CONNECTION=sqlite
DB_USERNAME=root
DB_PASSWORD=
- Depuis le dossier du projet, installer le projet, remettre à zéro la BDD, préremplir la base et lancer les tests unitaires
> composer install
> php artisan migrate:fresh
> php artisan db:seed
> php artisan test
- lancer le serveur
> php artisan serve
Routes disponibles
baseURL/webroutes
: rend une documentation des endpoints configurés.baseURL/logs
: rend une interface de lecture des logs.
Philosophie de développement
Bridge Pattern
Afin de permettre une abstraction et une réusabilité accrue, l'applicatif est entendu de manière modulaire.
Chaque module peut disposer d'une classe publique et dispose nécessairement d'une classe privée.
La classe publique, qui étend la classe privée de son module, est la seule à pouvoir discuter avec le routeur, elle fait toutes les vérifications d'intégrité des données en entrée, gère la transaction avec la base donnée (commit/rollback), capture les levées d'exception; elle est la seule à communiquer en sortie avec le client.
Une classe publique ne peut pas instancier une autre classe privée : elle dépend de sa classe mère. Totalement arbitraire, mais évite le spaghetti code, cela peut amener de la redondance sur les noms de méthodes, mais cela garantit une seule manière de faire transiter l'information.
Chaque classe privée est abstraite de la classe publique, les opérations de calcul et de communication avec le SGBD y résident.
Une classe privée peut utiliser une autre classe privée d'un autre module, ou d'une autre classe située en dehors du dossier app/Http/Controllers/Modules
. Dès lors la classe privée doit aussi comprendre les contrôles des arguments de méthodes mais ne capture pas les levées d'exception, elle ne fait qu'en émettre.
Gestion des levées d'exceptions
Afin de ne pas multiplier les gestions des exceptions personnalisées des différents modules et vendors, la classe publique se bornera à ne capter que deux types d'exceptions : Exception
et QueryException
.
Cela permettra de centraliser le traitement, particulièrement en cas de projet multilangue.
Il advient donc au développeur de capter par avance les exceptions personnalisées/vendors qui pourrait advenir et de renvoyer une Exception.
Une surcharge est disponible depuis app\Http\Controllers\Core\Exception.php
.
Routage
Le routage se configure à travers des fichiers plats xxx.routes.php disponibles à la racine de chaques dossier à partir de la racine app/Http/Controllers
.
La raison de travailler à partir de fichiers plats est de ne pas dépendre de la base de donnée : si la base de donnée crash, le routage est toujours opérationnel et peut toujours gérer le fait que la BDD soit indisponible.
En outre, cela permet très facilement de créer de nouvelles routes et surtout de pouvoir générer une documentation à la volée (disponible sur baseURL
/webroutes).
Enfin, ce système peut permettre d'avoir plusieurs type de fichier de routage et de permettre la gestion de plusieurs api en même temps sur un même système, par exemple, on peut disposer d'une API privée avec api.monsite.com et une autre publique sur web.monsite.com ou encore d'une autre réservées aux administrateur admin.monsite.com.
Architecture API
Chaque route (endpoint) est adossée à une méthode HTTP :
- GET : lit une information
- POST : créer une information
- PATCH : met à jour une information
- DELETE : supprime une information
Pour une même route, avec la même syntaxe, en fonction de la méthode utilisée, l'action ne sera pas la même.
Le retour de chaque route comporte au moins une clé : status
.
Cette clé prend en valeur 0 ou 1 sous la forme d'un entier.
Quand la valeur est 1, l'opération, quelle qu'elle soit, est réussie, si la valeur est 0, une erreur est survenue.
Si status
est égal à 0, alors une autre clé est nécessairement disponible : msg
.
La clé msg
doit contenir le retour d'erreur pour le client, dans la langue voulue.
On s'affranchit donc des codes HTTP de retour : ça fonctionne ou ça ne fonctionne pas.