Créé en 2022 et modifié le 21 Mar 2022

Créé en 2022 et modifié le 21 Mar 2022

API SLIM

Slim est un micro Framework pour PHP.

route bonjour – méthode GET,  URI /bonjour

  • installer composer
  • créer un fichier composer.json

 

{
    "require": {
        "php": "7.*",
        "ext-mbstring": "*",
        "ext-mysqli": "*",
        "ext-json": "*",
        "ext-pdo": "*",
        "ext-pdo_mysql": "*",
        "slim/slim": "3.*",
        "zircote/swagger-php": "^2.0",
        "firebase/php-jwt": "^5.0"
    }        
}

 

  • en PHP7 ou supérieur, grâce à une invite de commande, exécuter
composer require slim/slim "3"

 

  • dans un fichier index.php, copier le code 
<?php 
require 'vendor/autoload.php';
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;

$app = new \Slim\App;
$app->get('/zaza', function(Request $request, Response $response){	
	return "wazaaaaaaaa";
});
$app->run();

 

  • tester le serveur sur  localhost/index.php/

  • tester la route zaza
  • modifier la route zaza par bonjour pour obtenir le message bonjour.

Exemple de code client functionSlim.js en JQ, à adapter en VueJS

$( document ).ready(function() {

$('#btn-valide').click(function(){ 
$.ajax({ 
      type: "GET",
      contentType: 'application/json; charset=utf-8',
      url: "http://localhost/serveur/bonjour",
     success: function(data){
         alert(data);
      }
 });
});
 });
  • démarrer le serveur (apache ou autre)
  • tester la route
  • dans un fichier /index.html, la page appellera la route bonjour grâce à Ajax avec la méthode GET.

</html>
———————————————————————– ANNEXE APACHE ————————————————————————————————————-

Pour le déploiement en ligne du serveur slim et éviter index.php à chaque route

dans un fichier .htaccess. Si le htaccess fait planter le serveur, des configurations du serveur Apache sont nécessaires. Enlever le htaccess et ajouter index.php à chaque uri.

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [QSA,L]
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept"
Header set Access-Control-Allow-Methods: "GET,POST,OPTIONS,DELETE,PUT"

 

 

Réaliser son API avec des attributs dans l’URI

La base de données

route chambre – méthode GET,  URI  /animal/{id}

  • Choisir et envoyer un id de l’animal au serveur SLIM.
  • Le serveur renverra la description de l’animal grâce à une fonction et un appel à la base de données.

Exemple de code client

  $( document ).ready(function() {

  $('#btn-new-liste').click(function(){ 
    let idx=$('#idx').val();
      $.ajax({ 
      type: "GET",
      url: "http://localhost/got/serveur/personnage/"+idx,
      success: function(data){  
        $("#result").html(data);
      }
    });
  });
 });

Exemple d’ajout de code index.php

$app->get('/personnage/{id}', function(Request $request, Response $response){
	$id = $request->getAttribute('id');
       return getPersonnage($id);
});
function connexion()
{
   return $dbh = new PDO("mysql:host=localhost;dbname=patisserie", 'root', '', array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
}
function getPersonnage($id)
{
	$sql = "SELECT * FROM gateau";
	try{
		$dbh=connexion();
		$statement = $dbh->prepare($sql);
		$statement->execute();
		 $result = $statement->fetchAll(PDO::FETCH_CLASS); 
                 return json_encode($result, JSON_PRETTY_PRINT);
	} catch(PDOException $e){
		return '{"error":'.$e->getMessage().'}';
	}
}

 

Réaliser son API avec des paramètres HTTP

route user – méthode GET,  URI /user

  • Ajouter un mot de passe à la table user
  • Envoyer l’email et le mot de passe de connexion.html au serveur SLIM.
  • Tester si l’email et le mot de passe existe grâce à une fonction et renvoyer le code 200 ou 401.

Exemple de code client JQ

$('#btn-valide').click(function(){ 
let id=$('#id').val();
let nom=$('#nom').val();
$.ajax({ 
      type: "GET",
      contentType: 'application/json; charset=utf-8',
      url: "http://localhost/got/serveur/user?id="+id+"&nom="+nom,
     success: function(data){
         alert(data);
      }
 });
});

Exemple de code client VueJS

<!doctype html>
<html lang="fr">
<head>
  <link   type="text/css"    rel="stylesheet"    href="https://unpkg.com/bootstrap/dist/css/bootstrap.min.css"  />
  <link   type="text/css"    rel="stylesheet"    href="https://unpkg.com/[email protected]/dist/bootstrap-vue.css"  />
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
  <script src="https://unpkg.com/[email protected]/dist/bootstrap-vue.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<div id="app">
    <b-container>
         <input v-model="idc" placeholder="numéro de chambre"/>
          <button v-on:click="ajax(idc)">valider</button>
    </b-container>
</div>
<script>
        var app =new Vue({
          el: '#app',
          data () {
            return {             
              idc: 0                
            }
          },
          methods: {
            ajax: function (idc, event) {
            axios({
              method: 'get',
              url: 'http://frebourg.es/api/index.php/chambre?idc='+idc,
              responseType: 'json',    
            })
               .then(async res => { 
                 if(res.status === 200) { 
                       alert('Ok!');
                       this.info=res.data;                     
                  } else if(res.status === 400) { 
                      let errorResponse = await res.json(); this.errors.push(errorResponse.error); }
               })  
            }
            }
        })
        </script>
</html>

 

Exemple d’ajout de code index.php

$app->post('/user', function(Request $request, Response $response){
	 $tb = $request->getQueryParams();
    $id = $tb["id"];
    $nom = $tb["nom"];
        //fonction de vérification d'utilisateur
	return checkUser($id, $nom);
});

function checkUser($id, $nom)
{
	$sql = "SELECT * FROM gateau";
	try{
		$dbh=connexion();
		$statement = $dbh->prepare($sql);
		$statement->execute();
		 $result = $statement->fetchAll(PDO::FETCH_CLASS); 
                 return json_encode($result, JSON_PRETTY_PRINT);
	} catch(PDOException $e){
		return '{"error":'.$e->getMessage().'}';
	}
}

 

route user – méthode POST,  URI /user

  • Réaliser un formulaire d’inscription d’utilisateur inscription.html.
  • Permettre l’ajout de l’utilisateur dans la base de données.

Exemple de code client

$('#btn-valide').click(function(){ 
let id=$('#id').val();
let nom=$('#nom').val();
$.ajax({ 
      type: "POST",
      contentType: 'application/json; charset=utf-8',
      url: "http://localhost/got/serveur/user?id="+id+"&nom="+nom,
     success: function(data){
         alert(data);
      }
 });
});

Exemple d’ajout de code index.php

$app->post('/user', function(Request $request, Response $response){
$tb = $request->getQueryParams(); 
$id = $tb["id"];
       	return insertUser($id, $nom);
});

function insertUser($id, $nom)
{
	$sql = "INSERT ...";
	...
}

Réaliser son API avec les méthodes HTTP PUT et DELETE

route user – méthode DELETE,  URI /user/{id}

  • Implémenter l’URI qui supprime un utilisateur spécifique.

route user – méthode PUT,  URI /user/{id}

  • Implémenter l’URI qui modifie l’email d’un utilisateur.

route chambres – méthode GET,  URI /animaux

  • Implémenter l’URI qui renvoie en JSON les informations des animaux.
  • Réaliser une page animaux.html qui affiche sous forme de tableau toutes les animaux.

 

Sécurisé son API avec des jetons

JSON Web Token (JWT) est un standard ouvert défini dans la RFC 7519. Disponible dans la plupart des langages pour l’échange sécurisé de jeton. On pourra obtenir les extensions nécessaires sur le site jwt.io.

 

  • Ajouter JWT grâce à composer.
composer require firebase/php-jwt
  • Permettre à un utilisateur d’obtenir un jeton valable 30 minutes lors de la connexion au site grâce à l’URI /obtentionToken. On enregistrera ce jeton en session JavaScript.
  • En cas d’erreur à la connexion (login et mot de passe incorrect) le serveur renverra un code HTTP 401 Unauthorized .

Exemple de code client

 $( "#btn-valide").click(function(event) {               
               $.ajax({ 
                type: "GET",
                url: urlServeur+"/obtentionToken",
                data: "pass="+ $("#password").val(),
                success: function(data){
                      sessionStorage.setItem('token', data);                               
                },
                error: function(XMLHttpRequest, textStatus, errorThrown) {      
                        $(".form-group-password").addClass("has-danger");
                        $("#password").addClass("form-control-danger");
                }             
                });
});

Exemple de code serveur

<?php 
require 'vendor/autoload.php';
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
use \Firebase\JWT\JWT;
use Firebase\JWT\Key;
$app = new \Slim\App;
error_reporting(E_ALL);
ini_set('display_errors', 1);

$app->get('/obtentionToken', function(Request $request, Response $response){	
	//vérification de l'utilisateur
	$tb = $request->getQueryParams(); 
        $login= $tb["login"];
        $pass= $tb["pass"];	
	$allowed= ckeckUser($login,$pass);
	if($allowed){
		$token=getTokenJWT();
		return $response->withJson($token,200);
	}else{
		return $response->withStatus(401);
	}
});

$app->post('/verifToken', function(Request $request, Response $response){
        $tb = $request->getQueryParams(); 
	$token = $tb["token "];
	if(validJWT($token)){
		//J'execute la fonction
	}else{
		//non autorisé
		return $response->withStatus(401);
	}	
});

 function getTokenJWT() {
   // Make an array for the JWT Payload
  $payload = array(
    //30 min
    "exp" => time() + (60 * 30)
  );
   // encode the payload using our secretkey and return the token
  return JWT::encode($payload, "secret");
}

  function validJWT($token) {
    $res = false;
    try {
        $decoded = JWT::decode($token, new Key($key, 'HS256'));       
    } catch (Exception $e) {
      return $res;
    }
    $res = true;
    return $res;  
  }
   
$app->run();

 

  • Sécuriser les routes permettant d’afficher les utilisateurs grâce à la vérification d’un jeton. On pourra s’inspirer de la route  /verifToken ci dessus.
  • Sécuriser toutes les routes permettant de modifier, ajouter ou supprimer un élément (POST, DELETE, PUT).

 

Logs et graphiques dynamiques

 

On utilise Chartjs pour générer des graphiques dynamiques. Il existe d’autres bibliothèques.

 

frebourg-ninja-diagramme

 

 

  • Réaliser une page statistiques.html et afficher les deux charts suivants :
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" ></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" ></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/js/bootstrap.min.js" ></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.js"></script>

<div class="container"> 
   <div class="row justify-content-md-center">
          <div class="col-10">
<canvas id="myChart" ></canvas>
<canvas id="myChart2" ></canvas>
</div>
</div>
</div>
<script>
var backgroundColor=[
                'rgba(255, 99, 132, 0.2)',
                'rgba(54, 162, 235, 0.2)',
                'rgba(255, 206, 86, 0.2)',
                'rgba(75, 192, 192, 0.2)',
                'rgba(153, 102, 255, 0.2)',
                'rgba(255, 159, 64, 0.2)'
            ];
var borderColor=[
               'rgba(255,99,132,1)',
                'rgba(54, 162, 235, 1)',
                'rgba(255, 206, 86, 1)',
                'rgba(75, 192, 192, 1)',
                'rgba(153, 102, 255, 1)',
                'rgba(255, 159, 64, 1)'
            ];

var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
    type: 'bar',
    data: {
        labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
        datasets: [{
            label: '# of Votes',
            data: [12, 19, 3, 5, 2, 3],
            backgroundColor: backgroundColor,
            borderColor: borderColor,
            borderWidth: 1
        }]
    },
    options: {
        scales: {
            yAxes: [{
                ticks: {
                    beginAtZero:true
                }
            }]
        }
    }
});

var ctx2 = document.getElementById("myChart2").getContext('2d');
var myDoughnutChart = new Chart(ctx2, {
    type: 'doughnut',
    data : {
    datasets: [{
        data: [10, 20, 30],
        backgroundColor: backgroundColor,
            borderColor: borderColor,
            borderWidth: 1
    }],   
    labels: [
        'Red',
        'Yellow',
        'Blue'
    ],    
}    
});
</script>

 

  • Afficher sous forme de diagramme le nombre d’animaux par enclos
  • Afficher le nombre de races par soigneurs