Programming Notes
Think it, Code it, Run it    moschini.cloud  

Rest e PHP
Data pubblicazione: 07 maggio 2023

Introduzione

Nel post precedente abbiamo visto cosa sono i servizi REST, insieme a qualche esempio su come possano essere invocati tramite Postman.

In questo articolo, vedremo come creare i servizi per le operazioni basilari (CRUD: Create, Read, Update, Delete) di gestione di una risorsa, utilizzando il linguaggio PHP e il database MySQL.

Poiché abbiamo bisogno di un database, oltre ad un ambiente di sviluppo PHP, ho scelto di utilizzare XAMPP che può essere scaricato da questo indirizzo.

XAMPP è una distribuzione gratuita di Apache contenente PHP e MySQL.


Definizione del database

Cominciamo con la creazione del database:

   Visualizza / nascondi il codice
-- creazione database
CREATE DATABASE phprest;

-- selezione database
USE phprest;

La risorsa che gestiremo è una tabella contenente articoli. Per semplicità, la tabella conterrà, oltre ad un campo id (primary key), i campi codice, descrizione e quantita, oltre a due campi created e updated valorizzati, rispettivamente, con la data di creazione del record e la data dell'ultimo aggiornamento.

Questo è lo script per la definizione della tabella articoli:

   Visualizza / nascondi il codice
-- creazione tabella
CREATE TABLE IF NOT EXISTS `Articoli` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `codice` varchar(256) NOT NULL,
  `descrizione` varchar(256),
  `quantita` int(11) NOT NULL,
  `created` datetime NOT NULL,
  `updated` datetime NOT NULL,
  PRIMARY KEY (`id`)
)ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=19;

Configurazione di Apache: modifichiamo il file .htaccess

Il file .htaccess è un semplice file di testo che permette di configurare Apache tramite direttive.

Quando viene inviata una richiesta ad Apache, questi, prima di eseguirla, controlla la presenza di un file .htaccess nella cartella del file richiesto o in una cartella superiore. Se è definito un file .htaccess, legge la configurazione e modifica la richiesta inviata (tipicamente, l'URL) in modo da rispettare le direttive specificate.

Il file .htaccess che utilizzeremo per il nostro progetto è questo:

# Abilita il modulo Apache mod_rewrite
RewriteEngine On

# Specifica l'URL che viene inviato attraverso le regole di riscrittura,
# ovvero imposta la base di riscrittura per le regole specificate.
# E' necessaria quando i file PHP non risiedono nella root ma in una cartella specifica
RewriteBase /demo/v1

# Continua a elaborare le regole sottostanti se una directory con il nome specificato nell'URL non esiste
RewriteCond %{REQUEST_FILENAME} !-d

# Continua a elaborare le regole sottostanti se un file con il nome specificato nell'URL non esiste
RewriteCond %{REQUEST_FILENAME} !-f

# Indica ad Apache di riscrivere tutte le richieste indirizzate al server in modo da inviarle ad un file index.php.
# Ad esempio, se un utente richiede l'URL http://<root>/products/1,
# la regola di riscrittura lo reindirizzerà a http://<root>/index.php?request=products/1
RewriteRule ^(.*)$ index.php?request=$1 [QSA,NC,L]

E' importante prestare attenzione all'istruzione RewriteRule ^(.*)$ index.php?request=$1 [QSA,NC,L]. Attraverso questo comando diciamo ad Apache di reindirizzare tutte le richieste verso index.php passando, in query string, il parametro ?request=$1, dove $1 è la parte dell' URI originario al netto della parte che riguarda la root. Ad esempio, se l'URI della richiesta fosse www.server.com/risorsa/35, allora $1 = "risorsa/35", per cui la richiesta sarebbe reindirizzata all'URI www.example.com/index.php/risorsa/35.

Quindi abbiamo bisogno di un file index.php che faccia da "orchestratore" per le richieste inviate al server.


Struttura del progetto

Creiamo una directory demo dentro la root che ci servirà per conservare i file PHP. All'interno creiamo una directory v1, utilizzata per il versioning, e, al suo interno, definiamo una struttura di directory in modo tale da avere questa situazione:

demo/
├─ v1/
│  ├─ api/
│  │  ├─ articoli/
│  ├─ class/
│  ├─ config/
│  ├─ index.php

La directory api, interna a v1, conterrà una directory per ogni risorsa gestita dalle nostre API (inizialmente solo la directory articoli).

All'interno di articoli andremo a definire i file PHP per le operazioni CRUD su questa risorsa.

La directory class conterrà un file per ogni risorsa gestita, all'interno del quale andremo a definire una classe che rappresenta l'entità della risorsa insieme ai metodi per le operazioni di lettura e scrittura.

La directory config conterrà i file di configurazione delle nostre API, in particolare quello relativo al database.

Il file index.php, come anticipato, servirà a gestire le richieste.

Quindi la struttura finale del progetto può essere schematizzata in questo modo:

demo/
├─ v1/
│  ├─ api/
│  │  ├─ articoli/
│  │  |  ├─ create.php
│  │  |  ├─ delete.php
│  │  |  ├─ read.php
│  │  |  ├─ readAll.php
│  │  |  ├─ update.php
│  ├─ class/
│  │  ├─ articoli.php
│  ├─ config/
│  │  ├─ database.php
│  ├─ index.php

Dettaglio dei file PHP

Vediamo ora, nel dettaglio, il codice utilizzato per definire i file PHP elencati.

File "database.php"

   Visualizza / nascondi il codice
<?php 
    class Database {
        private $host = "127.0.0.1";
        private $database_name = "phprest";
        private $username = "root";
        private $password = "";
        public $conn;
        public function getConnection(){
            $this->conn = null;
            try{
                $this->conn = new PDO("mysql:host=" . $this->host . ";dbname=" . $this->database_name, $this->username, $this->password);
                $this->conn->exec("set names utf8");
            }catch(PDOException $exception){
                echo "Errore di connessione al database: " . $exception->getMessage();
            }
            return $this->conn;
        }
    }  
?>

Come anticipato, qui troviamo la classe Database con i parametri per l'accesso alla base dati (nome del server, nome del database, utente e password) e il metodo che fornisce la connessione.

File "index.php"

   Visualizza / nascondi il codice
<?php
  header("Content-type:application/json");

  include_once 'config/database.php';
  include_once 'class/articoli.php';

  $http_verb = $_SERVER['REQUEST_METHOD'];

  if (in_array($http_verb, array("GET","POST","PATCH","DELETE"))) {
      foreach($_GET as $key => $value) {
          $params[$key] = $value;
      }
  }

  $request = explode('/', $_REQUEST['request']);
  $resource = $request[0];

  if (isset($request[1])) {
      $resource_id = $request[1];
  } else {
      $resource_id = '';
  }

  switch($http_verb) {
    case 'GET':
        if (!empty($resource_id)) {
          require_once('api/'.$resource.'/read.php');
        } else {
          require_once('api/'.$resource.'/readAll.php');
        }
        break;
    case 'POST':
        if ($params['op'] == 'create') {
          require_once('api/'.$resource.'/create.php');
        }
        break;
    case 'PATCH':
        if (!empty($resource_id)) {
          require_once('api/'.$resource.'/update.php');
        }
        break;
    case 'DELETE':
        if (!empty($resource_id)) {
          require_once('api/'.$resource.'/delete.php');
        }
        break;
  }
?>

Questo script è richiamato da qualunque richiesta effettuata verso il server, come da direttiva RewriteRule definita nel file .htaccess.

La logica implementata prevede il recupero del verbo con il quale è stato invocato il servizio ($http_verb = $_SERVER['REQUEST_METHOD'];), nonché della risorsa e dell'eventuale Id sul quale il servizio deve operare.

Per la lettura di queste informazioni, si accede all'array $_REQUEST con la chiave 'request', quindi, splittando il valore recuperato dall'array utilizzando il separatore '/', si valorizzano la risorsa e l'eventuale Id su cui lavorare.

A questo punto, in funzione del verbo utilizzato (GET, POST, PATCH, DELETE), si richiama il relativo script della risorsa.

Da notare:
  • se si utilizza il verbo GET (lettura), abbiamo due possibilità:
    • se l'Id è valorizzato, si invoca lo script single_read.php per la lettura di una sola risorsa, ovvero quella corrispondente all'Id;
    • se l'Id non è valorizzato, si invoca lo script read.php per la lettura di tutte le risorse.
  • le chiamate tramite i verbi PATCH e DELETE devono essere effettuate passando l'Id
  • con la chiamata tramite POST, si verifica che tra i parametri in query-string ci sia create; in questo modo potremmo utilizzare il verbo POST anche per altre funzionalità, ad esempio per ricerche, naturalmente specificando un parametro ad-hoc in query-string.

File "articoli.php"

   Visualizza / nascondi il codice
<?php
    class Articoli{
        // Connessione
        private $conn;
        // Tabella
        private $db_table = "articoli";
        // Colonne
        public $id;
        public $codice;
        public $descrizione;
        public $quantita;
        public $created;
        public $updated;
        // Connessione al database
        public function __construct($db){
            $this->conn = $db;
        }
        // Legge tutti gli articoli
        public function getArticoli(){
            $sqlQuery = "SELECT id, codice, descrizione, quantita, created, updated FROM " . $this->db_table . "";
            $stmt = $this->conn->prepare($sqlQuery);
            $stmt->execute();
            return $stmt;
        }
        // Inserisce un articolo
        public function createArticolo(){
            $sqlQuery = "INSERT INTO
                        ". $this->db_table ."
                        SET
                        codice = :codice, 
                        descrizione = :descrizione, 
                        quantita = :quantita, 
                        created = :created, 
                        updated = :updated";
        
            $stmt = $this->conn->prepare($sqlQuery);
        
            // Converte i tag HTML in testo
            $this->codice=htmlspecialchars(strip_tags($this->codice));
            $this->descrizione=htmlspecialchars(strip_tags($this->descrizione));
            $this->quantita=htmlspecialchars(strip_tags($this->quantita));
            $this->created=htmlspecialchars(strip_tags($this->created));
            $this->updated=htmlspecialchars(strip_tags($this->updated));
        
            // bind data
            $stmt->bindParam(":codice", $this->codice);
            $stmt->bindParam(":descrizione", $this->descrizione);
            $stmt->bindParam(":quantita", $this->quantita);
            $stmt->bindParam(":created", $this->created);
            $stmt->bindParam(":updated", $this->updated);
        
            if($stmt->execute()){
               $this->id = $this->conn->lastInsertId();
               return true;
            }
            return false;
        }
        // Legge un articolo
        public function getArticolo(){
            $sqlQuery = "SELECT
                        id, 
                        codice, 
                        descrizione, 
                        quantita, 
                        created, 
                        updated
                        FROM
                        ". $this->db_table ."
                        WHERE 
                        id = ?
                        LIMIT 0,1";
            $stmt = $this->conn->prepare($sqlQuery);
            $stmt->bindParam(1, $this->id);
            $stmt->execute();
            $dataRow = $stmt->fetch(PDO::FETCH_ASSOC);
			if ($dataRow) {
				$this->codice = $dataRow['codice'];
				$this->descrizione = $dataRow['descrizione'];
				$this->quantita = $dataRow['quantita'];
				$this->created = $dataRow['created'];
				$this->updated = $dataRow['updated'];
			}
        }
        // Aggiorna un articolo
        public function updateArticolo(){
            $sqlQuery = "UPDATE
                        ". $this->db_table ."
                        SET
                        codice = :codice, 
                        descrizione = :descrizione, 
                        quantita = :quantita, 
                        updated = :updated
                        WHERE 
                        id = :id";
        
            $stmt = $this->conn->prepare($sqlQuery);
        
            $this->codice=htmlspecialchars(strip_tags($this->codice));
            $this->descrizione=htmlspecialchars(strip_tags($this->descrizione));
            $this->quantita=htmlspecialchars(strip_tags($this->quantita));
            $this->updated=htmlspecialchars(strip_tags($this->updated));
            $this->id=htmlspecialchars(strip_tags($this->id));
        
            // Binding dei dati
            $stmt->bindParam(":codice", $this->codice);
            $stmt->bindParam(":descrizione", $this->descrizione);
            $stmt->bindParam(":quantita", $this->quantita);
            $stmt->bindParam(":updated", $this->updated);
            $stmt->bindParam(":id", $this->id);
        
            if($stmt->execute()){
               return true;
            }
            return false;
        }
        // Cancella un articolo
        function deleteArticolo(){
            $sqlQuery = "DELETE FROM " . $this->db_table . " WHERE id = ?";
            $stmt = $this->conn->prepare($sqlQuery);
        
            $this->id=htmlspecialchars(strip_tags($this->id));
        
            $stmt->bindParam(1, $this->id);
        
            if($stmt->execute()){
                return true;
            }
            return false;
        }
    }
?>

La classe Articoli rappresenta l'entità della risorsa articoli.

Qui troviamo la sua modellazione, insieme ai metodi per le operazioni di lettura e scrittura.

Nel dettaglio, sono stati implementati i metodi:

  • getArticoli: recupera i dati di tutti gli articoli;
  • createArticolo: crea un articolo;
  • getArticolo: legge un singolo articolo;
  • updateArticolo: aggiorna gli attributi di un articolo;
  • deleteArticolo: cancella un articolo.

Questi metodi saranno utilizzati dagli script PHP preposti alle operazioni CRUD sulla risorsa articoli.

File "create.php"

   Visualizza / nascondi il codice
<?php
  header("Access-Control-Allow-Origin: *");
  header("Content-Type: application/json; charset=UTF-8");
	
  include_once 'config/database.php';
  include_once 'class/articoli.php';
	
  $database = new Database();
  $db = $database->getConnection();
  $item = new Articoli($db);
	
  $data = json_decode(file_get_contents("php://input"));
	
  $item->codice = $data->codice;
  $item->descrizione = $data->descrizione;
  $item->quantita = $data->quantita;
  $item->created = date('Y-m-d H:i:s');
  $item->updated = date('Y-m-d H:i:s');
    
  $result = array();
  $result["result"] = "";
  $result["data"] = array();
	
  if($item->createArticolo()) {
     $result["result"] = 'Articolo inserito.';
     $result["data"] = array(
        "id" =>  $item->id,
        "codice" => $item->codice,
        "descrizione" => $item->descrizione,
        "quantita" => $item->quantita,
        "created" => $item->created,
        "updated" => $item->updated
	 );
   http_response_code(201);
  } else {
     $result["result"] = 'Articolo non inserito.';
     http_response_code(500);
  }
	
  echo json_encode($result);
?>

In questo script PHP troviamo l'implementazione della creazione di un nuovo articolo.

Questa operazione ha bisogno, naturalmente, della connessione al database, che viene recuperata tramite il metodo getConnection.

Quindi si crea una istanza della classe Articoli, le cui proprietà sono valorizzate con il contenuto del body (payload) specificato nella chiamata al servizio.

Il body viene letto tramite json_decode(file_get_contents("php://input")), memorizzato nella variabile $data e utilizzato per valorizzare le proprietà dell'istanza della classe Articoli tramite gli assegnamenti $item->... = $data->....

Le proprietà created e updated sono valorizzate con la data e l'ora di sistema.

Si passa, quindi, a definire la variabile $result, ovvero la risposta alla richiesta di creazione di un articolo. Questa informazione è composta da due elementi:

  • result: indica se l'operazione è andata a buon fine (messaggio testuale);
  • data: riporta i valori degli attributi della entità inserita.

Si arriva ad invocare il metodo createArticolo della classe Articoli che esegue l'inserimento del record nella tabella articoli del database.

Se l'inserimento è andato a buon fine, l' attributo result è valorizzato con Articolo inserito. e data è popolata con i dati dell'entità inserita, altrimenti result assume il valore Articolo non inserito. e data non è definita.

Attraverso il comando http_response_code definiamo il codice di risposta HTTP del servizio.

File "delete.php"

   Visualizza / nascondi il codice
<?php
  header("Access-Control-Allow-Origin: *");
  header("Content-Type: application/json; charset=UTF-8");

  include_once 'config/database.php';
  include_once 'class/articoli.php';
  
  $database = new Database();
  $db = $database->getConnection();
  
  $item = new Articoli($db);
  $item->id = isset($resource_id) ? $resource_id : die();
  
  $result = array();
  $result["result"] = "";
	
  if($item->deleteArticolo()) {
    $result["result"] = 'Articolo cancellato.';
    http_response_code(200);
  } else {
    $result["result"] = 'Articolo non cancellato.';
    http_response_code(500);
  }
	
  echo json_encode($result);
?>

In questo script PHP troviamo l'implementazione della cancellazione di un articolo.

La parte relativa alla connessione al database è sostanzialmente identica a quella definita nel file create.php.

Si controlla che l'Id sia definito, altrimenti lo script interrompe la sua esecuzione.

L'istanza della classe Articoli serve per invocare il metodo deleteArticolo, il cui esito ci permette di definire la variabile $result con la risposta restituita e il codice di risposta HTTP.

File "read.php"

   Visualizza / nascondi il codice
<?php
    header("Access-Control-Allow-Origin: *");
    header("Content-Type: application/json; charset=UTF-8");
	
    include_once 'config/database.php';
    include_once 'class/articoli.php';
	
    $database = new Database();
    $db = $database->getConnection();
    $item = new Articoli($db);

    $item->id = isset($resource_id) ? $resource_id : die();
  
    $result = array();
    $result["result"] = "";
    $result["data"] = array();
  
    $item->getArticolo();
    if($item->codice != null) {
        $result["data"] = array(
            "id" =>  $item->id,
            "codice" => $item->codice,
            "descrizione" => $item->descrizione,
            "quantita" => $item->quantita,
            "created" => $item->created,
            "updated" => $item->updated
        );
    $result["result"] = 'Articolo trovato.';
    http_response_code(200);
    }
    else {
        $result["result"] = 'Articolo non trovato.';
        http_response_code(404);
    }
	
    echo json_encode($result);
?>

In questo script PHP troviamo l'implementazione della lettura di un articolo, dato il suo Id.

La parte importante di questo script è la chiamata al metodo getArticolo.

Se l'esito è positivo, ovvero se è valorizzata la proprietà codice dell'istanza dell'articolo, si valorizza l'attributo data della variabile $result con l'array contenente le proprietà dell'istanza dell'articolo, oltre all'attributo result con il valore Articolo trovato.. Se l'esito della lettura è negativo, si valorizza solo l'attributo result con il valore Articolo non trovato. e il codice di risposta HTTP è settato a 404 (Not Found).

File "readAll.php"

   Visualizza / nascondi il codice
<?php
    header("Access-Control-Allow-Origin: *");
    header("Content-Type: application/json; charset=UTF-8");
    
    include_once 'config/database.php';
    include_once 'class/articoli.php';
	
    $database = new Database();
    $db = $database->getConnection();
    $articoli = new Articoli($db);
    $stmt = $articoli->getArticoli();
    $itemCount = $stmt->rowCount();

    if($itemCount > 0) {
        $result = array();
        $result["body"] = array();
        $result["itemCount"] = $itemCount;
        while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
            extract($row);
            $e = array(
                "id" => $id,
                "codice" => $codice,
                "descrizione" => $descrizione,
                "quantita" => $quantita,
                "created" => $created,
                "updated" => $updated
            );
            array_push($result["body"], $e);
        }
        http_response_code(200);
        echo json_encode($result);
    }
    else {
        http_response_code(404);
        echo json_encode(
            array("message" => "Nessun record trovato.")
        );
    }
?>

In questo script PHP troviamo l'implementazione della lettura di tutti gli articoli.

A differenza dello script read.php, il metodo invocato è getArticoli e il risultato (variabile $result) contiene i seguenti attributi:

  • itemCount: è valorizzato con il numero di articoli letti;
  • body: è un array in cui ogni elemento contiene i dati di un articolo letto.

File "update.php"

   Visualizza / nascondi il codice
<?php
    header("Access-Control-Allow-Origin: *");
    header("Content-Type: application/json; charset=UTF-8");
	
    include_once 'config/database.php';
    include_once 'class/articoli.php';
    
    $database = new Database();
    $db = $database->getConnection();
    $item = new Articoli($db);
    
    $data = json_decode(file_get_contents("php://input"));
    
    $item->id = isset($resource_id) ? $resource_id : die();
	
    $item->codice = $data->codice;
    $item->descrizione = $data->descrizione;
    $item->quantita = $data->quantita;
    $item->updated = date('Y-m-d H:i:s');
    
    $result = array();
    $result["result"] = "";
    $result["data"] = array();
	
    if($item->updateArticolo()) {
       $result["result"] = 'Articolo aggiornato.';
       $result["data"] = array(
          "id" =>  $item->id,
          "codice" => $item->codice,
          "descrizione" => $item->descrizione,
          "quantita" => $item->quantita,
          "updated" => $item->updated
       );
       http_response_code(200);
    } else {
       $result["result"] = 'Articolo non aggiornato.';
       http_response_code(500);
    }
	  
    echo json_encode($result);
?>

In questo script PHP troviamo l'implementazione dell'aggiornamento di un articolo.

Il metodo invocato stavolta è updateArticolo, il cui esito condiziona la riposta fornita dopo la chiamata al servizio.

In assenza di errori, il servizio risponde con i dati aggiornati dell'articolo e il codice di risposta HTTP è 200, altrimenti è 500.


Testiamo con Postman

Dopo aver scritto un po' di codice PHP, è arrivato il momento di testarne il funzionamento.

Per fare questo utilizzeremo POSTMAN, introdotto in questo articolo

Iniziamo con il test del servizio per la creazione di un articolo, in modo da popolare la relativa tabella.

Il servizio per la creazione di un articolo utilizza il verbo POST e, nell'URI, ha il parametro op=create in query string.

In sintesi, il servizio ha questi parametri:

Verbo
POST
URI
http://localhost/demo/v1/articoli/?op=create
Body
{
   "codice": "Computer",
   "descrizione": "Computer con 32 Gb RAM",
   "quantita": 10
}

Dopo la chiamata al servizio, la risposta è:

Status
200 OK
Response
{
   "result": "Articolo inserito.",
   "data": {
      "id": "1",
      "codice": "Computer",
      "descrizione": "Computer con 32 Gb RAM",
      "quantita": "10",
      "created": "2023-05-06 17:22:02",
      "updated": "2023-05-06 17:22:02"
   }
}

Lo Status = 200 OK indica che l'esecuzione del servizio è terminata senza errori.

Verifichiamo se nella tabella articoli sia stato effettivamente inserito il record.

Per questo, invochiamo il servizio che interroga tutti gli articoli, con questi parametri:

Verbo
GET
URI
http://localhost/demo/v1/articoli/

La risposta è:

Status
200 OK
Response
{
   "body": [
      {
      "id": 1,
      "codice": "Computer",
      "descrizione": "Computer con 32 Gb RAM",
      "quantita": 10,
      "created": "2023-05-06 17:22:02",
      "updated": "2023-05-06 17:22:02"
      }
   ],
   "itemCount": 1
}

Anche in questo caso, lo Status = 200 OK ci dice che la chiamata al servizio è terminata con successo e la response elenca tutti gli articoli presenti nella tabella articoli del database.

Inseriamo altri due articoli, indicando nel body questi dati:

Body primo articolo
{
   "codice": "Tastiera",
   "descrizione": "Tastiera meccanica",
   "quantita": 20
}
Body secondo articolo
{
   "codice": "Mouse",
   "descrizione": "Mouse silenzioso",
   "quantita": 30
}

Il servizio da invocare è quello con il verbo POST che abbiamo utilizzato in precedenza.

Interroghiamo, di nuovo, tutti gli articoli presenti e otteniamo questi dati:

Status
200 OK
Response
{
   "body": [
      {
         "id": 1,
         "codice": "Computer",
         "descrizione": "Computer con 32 Gb RAM",
         "quantita": 10,
         "created": "2023-05-06 17:22:02",
         "updated": "2023-05-06 17:22:02"
      },
      {
         "id": 2,
         "codice": "Tastiera",
         "descrizione": "Tastiera meccanica",
         "quantita": 20,
         "created": "2023-05-06 18:14:31",
         "updated": "2023-05-06 18:14:31"
      },
      {
         "id": 3,
         "codice": "Mouse",
         "descrizione": "Mouse silenzioso",
         "quantita": 30,
         "created": "2023-05-06 18:14:34",
         "updated": "2023-05-06 18:14:34"
      }
   ],
   "itemCount": 3
}

Come auspicato, troviamo i tre articoli inseriti.

Per interrogare il singolo articolo utilizzando il suo Id, possiamo utilizzare il verbo GET, specificando nell'URI l'Id dell'articolo:

Verbo
GET
URI
http://localhost/demo/v1/articoli/2

Come possiamo vedere, nell'URI abbiamo specificato l'Id dell'articolo subito dopo il nome della risorsa articoli e utilizzando il separatore /.

Il risultato della richiesta è:

Colonna 1Colonna 2Colonna 3
Status
200 OK
Response
{
   "result": "Articolo trovato.",
   "data": {
      "id": "2",
      "codice": "Tastiera",
      "descrizione": "Tastiera meccanica",
      "quantita": 20,
      "created": "2023-05-06 18:14:31",
      "updated": "2023-05-06 18:14:31"
   }
}

Altra operazione importante è quella di aggiornamento (UPDATE).

In questo caso, il verbo da utilizzare è PATCH, nell'URI dobbiamo specificare l'Id dell'articolo da modificare e nel body definiremo tutti gli attributi dell'entità Articolo con il valore da assegnare:

Verbo
PATCH
URI
http://localhost/demo/v1/articoli/2
Body
{
   "codice": "Tastiera",
   "descrizione": "Tastiera meccanica",
   "quantita": 50
}

In questo esempio, abbiamo modificato la quantità da 20 a 50; interrogando di nuovo l'articolo con Id = 2, abbiamo la conferma che il dato è stato modificato:

Status
200 OK
Response
{
   "result": "Articolo trovato.",
   "data": {
      "id": "2",
      "codice": "Tastiera",
      "descrizione": "Tastiera meccanica",
      "quantita": 50,
      "created": "2023-05-06 18:14:31",
      "updated": "2023-05-07 16:08:05"
   }
}

L'ultima operazione è la cancellazione (DLETE).

Il verbo da utilizzare è DELETE e nell'URI definiamo l'Id dell'articolo da cancellare:

Verbo
DELETE
URI
http://localhost/demo/v1/articoli/2

In questo caso, se l'esito è positivo, la risposta del servizio sarà:

Status
200 OK
Response
{
   "result": "Articolo cancellato."
}

In effetti, richiamando ancora una volta la lettura dell'articolo, otteniamo questa risposta:

Status
200 OK
Response
{
   "result": "Articolo non trovato.",
   "data": []
}

I sorgenti dell' esempio possono essere scaricati da questo link.