Ce référentiel contient un petit cadre capable de faire un restapi facilement avec PHP
PDOUtilsRepository nettoyé afin d'utiliser PDOUtilsApiException.phpRest::handleRequest pour retourner un HTTP 409 lorsque l'exception est élevéeRest::existFileSingletonController->getAllRest::scalePicturedbIgnoreController->getByFieldsRest::uploadFileRest::$uploadDirRest::getUploadDir()Rest::configureUploadDir()Rest::createDirectoryRecursive()Guards ajoutéeRole supplémentaireKeyValue et KeyValueListService et Repository mis à jourCredentials ajoutéedeleteByField()getByField() mise à jour, il renvoie maintenant Model[] au lieu du Model Pour commencer, vous devrez créer un dossier (je l'ai nommé /rest ) et placer le dossier ApiRest à l'intérieur. Le fichier principal sera api.php : il créera le restapi, se connectera à la base de données et écoutera les demandes.
Voici le contenu par défaut de ce fichier:
<?php
require_once __DIR__ . " /ApiRest/RestAPI.php " ;
header ( ' Content-Type: application/json ' );
header ( ' Access-Control-Allow-Headers: Content-Type, enctype, token ' );
header ( ' Access-Control-Allow-Origin: * ' );
header ( ' Access-Control-Allow-Methods: GET, POST, PUT, DELETE ' );
$ restAPI = new RestAPI ( " localhost " , " myDB " , " root " , "" );
// You can add an argument to improve the security of your session like this :
//$restAPI = new RestAPI("localhost", "myDB", "root", "", "m*;rO)P7^)3'k[F'S~h0Lx7{zN%`6S");
Rest:: configureUploadDir ( " rest-upload " );
echo $ restAPI -> handleRequest (); Maintenant, le Restapi est prêt à l'emploi. Vous pouvez le vérifier avec Postman et frapper l'URL avec la méthode GET : http://your-domain/your-path/rest/api.php/user .
C'est cool, mais comment le restapi gère cela?
api.php (ici c'est le mot user )user existeuser/include.php existeUserControllerprocessUrl Dans le répertoire user , vous trouverez un exemple pour ajouter des chemins à votre repos API pour un objet User . Chaque fichier lié à un objet / classe / table spécifique devra être dans le même dossier et suivre les mêmes règles que l'utilisateur:
/modelname/include.phpModelName.controller.phpModelName.model.phpModelName.repository.phpModelName.service.php Les contrôleurs sont la première couche appelée par le restapi. Ils doivent être nommés comme ceci: modelClassName + "Controller" . Par défaut, ces chemins sont générés par défaut:
api.php/modelClassNameapi.php/modelClassName/$idapi.php/modelClassNameapi.php/modelClassNameapi.php/modelClassName/$idPar défaut, chaque chemin généré est associé au gardien Loggeuard. Si vous souhaitez supprimer le garde, vous devrez remplacer l'apiroute en le déclarant dans votre contrôleur.
Vous pouvez ajouter un filtre sur la fonction GetAll en ajoutant des valeurs Get sur l'URL. Exemple :
api.php/modelClassName?lastname=Doe
Voici un exemple de classe UserController:
<?php
// FILE rest/user/User.controller.php
require_once __DIR__ . " /../ApiRest/Rest.php " ;
require_once __DIR__ . " /../ApiRest/Controller.php " ;
class UserController extends Controller {
public function __construct ( string $ modelName ) {
parent :: __construct ( $ modelName );
$ this -> createApiRoute (Rest:: PUT , ' login ' , " login " );
$ this -> createApiRoute (Rest:: POST , ' picture ' , " uploadPicture " , [ new LoginGuard ()]);
}
/* PUT */
public static function login ( array $ params , stdClass $ body ): string {
$ user = User:: fromJSON ( $ body );
return static :: $ service -> login ( $ user );
}
public static function uploadPicture (): string {
$ fileName = " htmlInputName " ;
$ newName = " profilePicture.png " ;
Rest:: uploadFile ( $ fileName , $ newName );
return "" ;
}
} Lorsque vous appelez la fonction createApiRoute() , le deuxième paramètre correspond au chemin de la demande. Dans cette chaîne, vous pouvez ajouter des paramètres dynamiques comme celui-ci 'customPath/$param1/$param2/anything' . Ensuite, lorsque la fonction associée sera appelée, vous trouverez des valeurs de $param1 et $param2 sur la variable $params :
var_dump ( $ params );
// print :
// array(
// "param1" => "value1",
// "param2" => "value2",
//)Vous pouvez remplacer un itinéraire avec un autre sans le retirer, s'ils n'ont pas la même quantité de paramètres. Par exemple, ces itinéraires seront conservés:
$ this -> createApiRoute (Rest:: GET , ' $id ' , " getById " );
$ this -> createApiRoute (Rest:: GET , ' current ' , " getCurrent " );Si possible, le «courant» de l'itinéraire sera déclenché. Si ce n'est pas le cas, l'itinéraire «$ id» sera déclenché.
Les services sont la couche suivante appelée par les contrôleurs: ils se trouvent entre les classes de contrôleur et les classes de référentiel. Les services sont utilisés pour obtenir des données des classes Repository et faire des données de traitement.
Les cours Service peuvent également appeler d'autres services pour traverser les données et effectuer un processus spécial.
Par défaut, les fonctions associées aux chemins de contrôleur sont générées:
getAll()getByID(string $id)create()update()delete(string $id)Voici un exemple de classe d'utilisateurs:
<?php
// FILE rest/user/User.service.php
require_once __DIR__ . " /../ApiRest/Service.php " ;
class UserService extends Service {
public function login ( User $ user ): string {
return $ this -> repository -> login ( $ user );
}
function initialize () { }
} Si vous souhaitez utiliser un autre Service dans ces cours, vous devez le déclarer et initialiser la classe Service dans la fonction initialize comme celle-ci:
<?php
class UserService extends Service {
/** @var $bookService BookService */
public $ bookService ;
public function login ( User $ user ): string {
return $ this -> repository -> login ( $ user );
}
function initialize () {
$ this -> bookService = BookService:: getInstance ( " Book " );
}
}Les référentiels sont la couche finale appelée par les services. Ils contient des requêtes SQL et obtiennent des modèles objets à partir de la base de données.
Identique aux services, par défaut, ces fonctions sont disponibles:
getAll()getByID(string $id)create()update()delete(string $id)Voici un exemple de classe UserRepository:
<?php
// FILE rest/user/User.repository.php
require_once __DIR__ . " /../ApiRest/Repository.php " ;
class UserRepository extends Repository {
public function __construct () {
parent :: __construct ( " user " , ' User ' );
}
public function login ( User $ user ): string {
$ fields = new KeyValueList ([
new KeyValue ( " name " , $ user -> name ),
new KeyValue ( " password " , $ user -> password )
]);
$ matchedUsers = $ this -> getByFields ( $ fields );
if ( count ( $ matchedUsers ) != 1 )
throw new Exception ( " UserRepository->login() : $ matchedUsers have a size of " . count ( $ matchedUsers ) . " instead of 1 ! " );
$ loggedUser = $ matchedUsers [ 0 ];
if ( $ loggedUser )
return Rest:: IDToToken ( $ loggedUser -> id );
else
return "" ;
}
}Si vous souhaitez utiliser des requêtes SQL personnalisées, vous pouvez utiliser la classe PDoutils afin de les exécuter. Voici un exemple:
$ query = " < CUSTOM_SELECT_QUERY > " ;
$ PDOStatement = PDOUtils:: executeQuery ( $ query );
return static :: getByPDOStatement ( $ PDOStatement ); Il y a des fonctions que vous pouvez utiliser à partir de PDOUtils :
executeQuery(query)executeQueryWithParameter(query, keyValue)executeQueryWithParameters(query, KeyValueList)Les modèles sont les classes représentant une ligne dans la base de données.
Lorsque les données sont récupérées de la base de données, les booléens ne seront pas égaux à true / false mais à '1' / '0' . Pour récupérer nos booléens volés, vous pouvez appeler la fonction preserveBooleans() pour convertir les champs booléens.
Pour marquer un champ comme un champ booléen, appelez simplement cette fonction à l'intérieur du constructeur: addBoolean("booleanField1", "booleanField2", ...)
De la même manière, vous pouvez marquer un champ en tant que jsonignore en appelant la fonction addIgnore("ignoredField1", ...) . Ensuite, pour convertir les instances du modèle en JSON, appelez la fonction encode() !
Il existe une autre fonction: addDbIgnore("field1", ...) utilisé pour spécifier quels champs ne sont pas stockés dans la base de données.
Les classes de modèles peuvent être récupérées de JSON à l'aide de cette fonction statique: Model::fromJSON(stdClass $data) .
Les gardes sont utilisés pour restreindre l'accès aux données en fonction du rôle de l'utilisateur. Trois gardes sont créés par défaut:
AdminGuardModeratorGuardLoginGuard Ils étendent tous la classe de résumé Guard et mettent en œuvre la fonction authorizeAccess(): bool . Vous pouvez également créer votre propre garde en suivant les mêmes règles, puis en ajoutant une nouvelle ligne dans le fichier include.php dans le répertoire Guard .
Les gardes sont appelés dans les classes des contrôleurs, lorsque vous déclarez l'itinéraire. Notez qu'un itinéraire peut avoir 0, 1 ou plusieurs gardes.
Une exception peut être soulevée lorsqu'il y a un problème à imprimer affiché sur le site Web frontal. Pour ce faire, vous devez lancer une ApiException et le serveur répondra avec une erreur HTTP 409 .
La classe ApiException étend la classe Exception , mais elle n'utilise pas de paramètres de la superclasse.
Cette classe est fabriquée de manière à utiliser facilement un outil FronDend d'internationalisation: il contient un paramètre key qui peut être la clé de la traduction dans le fichier JSON et un paramètre parameters qui contiennent les données à transmettre. Par exemple, voici une apiexception et le fichier d'internationalisation JSON associé:
throw new ApiException ( " api-error.error1 " , [ " name " => ' John ' ]);{
"api-error" : {
"error1" : {
"title" : " Hey ! " ,
"text" : " Hello {{name}} "
}
}
} Lorsque vous utilisez une apiexception, ces données seront stockées dans la propriété error de l'élément JavaScript HttpErrorResponse .
Ajoutez la capacité de forcer le type du champ de chaque modèle autrement, aucune amélioration future prévue maintenant. Cela ne signifie pas que le package ne sera pas mis à jour!