PHP e API RESTful: validazione e sanitizzazione dei dati in un endpoint

by theArchitect
SHARE
PHP e API RESTful: validazione e sanitizzazione dei dati in un endpoint
© Guida-HTML5.it

Introduzione

Quando si sviluppa un’API RESTful in PHP, uno degli aspetti più importanti non è solo ricevere i dati, ma verificarli correttamente prima di usarli. Un endpoint che accetta input senza controlli può generare errori, dati incoerenti o, nei casi peggiori, vulnerabilità di sicurezza.

In questo tutorial vedremo come costruire un endpoint RESTful che riceve dati JSON e li sottopone a validazione e sanitizzazione. L’obiettivo è creare una base robusta per operazioni come la creazione di risorse, l’aggiornamento di record o la registrazione di dati da parte del client.

Il caso pratico sarà un endpoint POST /api/contacts che crea un contatto. Il client invia nome, email e telefono; il server controlla che i valori rispettino le regole attese e risponde con JSON coerente.

Codice completo

<?php
declare(strict_types=1);

header(´Content-Type: application/json; charset=utf-8´);
header(´Access-Control-Allow-Origin: *´);
header(´Access-Control-Allow-Methods: POST, OPTIONS´);
header(´Access-Control-Allow-Headers: Content-Type, Authorization´);

if ($_SERVER[´REQUEST_METHOD´] === ´OPTIONS´) {
    http_response_code(204);
    exit;
}

if ($_SERVER[´REQUEST_METHOD´] !== ´POST´) {
    http_response_code(405);
    echo json_encode([
        ´success´ => false,
        ´error´ => ´Metodo non consentito´
    ]);
    exit;
}

// Legge il corpo JSON inviato dal client
$rawInput = file_get_contents(´php://input´);
$data = json_decode($rawInput, true);

// Controlla che il JSON sia valido
if (!is_array($data)) {
    http_response_code(400);
    echo json_encode([
        ´success´ => false,
        ´error´ => ´JSON non valido´
    ]);
    exit;
}

// Funzione di supporto per sanitizzare stringhe
function sanitizeString(?string $value): string
{
    return trim(filter_var($value ?? ´´, FILTER_SANITIZE_SPECIAL_CHARS));
}

// Funzione di supporto per validare email
function isValidEmail(string $email): bool
{
    return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}

$errors = [];

// Recupero e sanitizzazione dei campi
$name = sanitizeString($data[´name´] ?? null);
$email = sanitizeString($data[´email´] ?? null);
$phone = sanitizeString($data[´phone´] ?? null);

// Validazione nome
if ($name === ´´) {
    $errors[´name´] = ´Il nome è obbligatorio´;
} elseif (mb_strlen($name) < 2) {
    $errors[´name´] = ´Il nome deve contenere almeno 2 caratteri´;
}

// Validazione email
if ($email === ´´) {
    $errors[´email´] = ´L´email è obbligatoria´;
} elseif (!isValidEmail($email)) {
    $errors[´email´] = ´Formato email non valido´;
}

// Validazione telefono
if ($phone === ´´) {
    $errors[´phone´] = ´Il telefono è obbligatorio´;
} elseif (!preg_match(´/^[0-9+-s()]{6,20}$/´, $phone)) {
    $errors[´phone´] = ´Formato telefono non valido´;
}

if (!empty($errors)) {
    http_response_code(422);
    echo json_encode([
        ´success´ => false,
        ´message´ => ´Errore di validazione´,
        ´errors´ => $errors
    ], JSON_UNESCAPED_UNICODE);
    exit;
}

// Simulazione di salvataggio: qui potresti usare PDO e un database
$contact = [
    ´id´ => 101,
    ´name´ => $name,
    ´email´ => $email,
    ´phone´ => $phone,
    ´created_at´ => date(´c´)
];

http_response_code(201);
echo json_encode([
    ´success´ => true,
    ´message´ => ´Contatto creato con successo´,
    ´data´ => $contact
], JSON_UNESCAPED_UNICODE);
?>

Spiegazione

Il codice precedente mostra una struttura tipica di un endpoint RESTful in PHP. Vediamo i passaggi principali.

1. Impostazione degli header

Il primo blocco definisce il tipo di risposta e alcune regole utili per le richieste cross-origin:

  • Content-Type: application/json indica che la risposta sarà JSON.
  • Access-Control-Allow-Origin abilita le richieste da altri domini, utile se il frontend è separato dal backend.
  • Access-Control-Allow-Methods limita i metodi consentiti.
  • Access-Control-Allow-Headers specifica gli header accettati dal server.

La gestione della richiesta OPTIONS è importante per il preflight CORS: se il browser la invia, il server risponde con 204 No Content e termina subito l’esecuzione.

2. Controllo del metodo HTTP

L’endpoint accetta solo POST. Se arriva un altro metodo, il server risponde con 405 Method Not Allowed. Questo è un comportamento corretto in un’API RESTful, perché ogni endpoint dovrebbe accettare solo i metodi previsti.

3. Lettura del JSON

In PHP, i dati inviati nel corpo di una richiesta JSON si leggono con php://input. Dopo aver ottenuto la stringa grezza, la decodifichiamo con json_decode() in un array associativo.

Se il JSON non è valido, l’API risponde con 400 Bad Request. Questo evita di continuare l’elaborazione con dati corrotti o incompleti.

4. Sanitizzazione dei dati

La sanitizzazione non sostituisce la validazione: serve a ripulire i dati da caratteri indesiderati o potenzialmente problematici. Nel tutorial usiamo sanitizeString(), che applica trim() e FILTER_SANITIZE_SPECIAL_CHARS.

Questo passaggio è utile soprattutto quando i dati verranno mostrati in una pagina HTML o salvati in un sistema che può essere esposto a contenuti malevoli.

5. Validazione dei campi

Ogni campo viene controllato con regole precise:

  • name: obbligatorio e lungo almeno 2 caratteri.
  • email: obbligatoria e con formato valido.
  • phone: obbligatorio e composto solo da caratteri ammessi come numeri, spazi, parentesi, trattini e simbolo +.

Gli errori vengono raccolti in un array associativo, così il client può capire esattamente quali campi correggere.

6. Risposta con HTTP 422

Se la validazione fallisce, il server restituisce 422 Unprocessable Entity. È una scelta molto usata nelle API RESTful quando la richiesta è formalmente corretta, ma i dati non rispettano le regole di business.

7. Risposta di successo

Se tutto è valido, l’endpoint simula la creazione di un contatto e risponde con 201 Created. In un progetto reale, al posto della simulazione inseriresti una query SQL con PDO, idealmente usando prepared statement.

Best practice

  • Separare validazione e salvataggio: prima controlla i dati, poi scrivili nel database.
  • Usare codici HTTP corretti: 400 per JSON non valido, 405 per metodo errato, 422 per errori di validazione, 201 per creazione riuscita.
  • Restituire errori dettagliati: un array di errori per campo rende l’API più facile da usare lato frontend.
  • Non fidarti mai dell’input del client: anche se arriva da un form interno, i dati devono essere sempre verificati.
  • Usare prepared statement con PDO: la validazione non sostituisce la protezione contro SQL injection.
  • Tenere coerente il formato delle risposte: tutte le risposte dell’API dovrebbero seguire una struttura simile, con campi come success, message, data ed errors.
  • Validare anche lato server: la validazione JavaScript nel frontend è utile, ma non basta mai da sola.

Riepilogo

La validazione e sanitizzazione dei dati sono fondamentali in qualsiasi API RESTful scritta in PHP. In questo tutorial hai visto come:

  • leggere correttamente un payload JSON;
  • controllare il metodo HTTP della richiesta;
  • sanitizzare stringhe in ingresso;
  • validare campi obbligatori e formati specifici;
  • restituire risposte JSON coerenti con codici HTTP appropriati.

Questa struttura è facilmente riutilizzabile in molti contesti: creazione utenti, registrazione ordini, gestione contatti o inserimento di qualsiasi risorsa in un sistema RESTful. Se impari a trattare bene i dati in ingresso, le tue API diventano più sicure, affidabili e facili da mantenere.

Approfondisci con risorse ufficiali

  • PHP Manual - json_decode(): documentazione ufficiale per la decodifica JSON.
  • PHP Manual - filter_var(): utile per validazione e sanitizzazione.
  • PHP Manual - mb_strlen(): per contare correttamente i caratteri nelle stringhe multibyte.
  • MDN Web Docs - HTTP response status codes: panoramica completa sui codici di stato HTTP.
  • OWASP API Security Top 10: guida fondamentale per sviluppare API più sicure.

SHARE