Abbreviare gli URL con PHP e MySQL

Short link

L'implementazione di un sistema di abbreviazione degli URL è piuttosto semplice con PHP e MySQL.

La nostra struttura è davvero semplice: un client Web effettua una richiesta POST autenticata a un endpoint delle API passando l'URL completo da abbreviare. Qui salviamo l'URL completo in una tabella del database insieme alla stringa generata casualmente che identifica tale URL. Quindi restituiamo questa stringa al client. Se l'URL è già nel database, restituiamo immediatamente la stringa casuale memorizzata come identificatore dell'URL originale.

Quindi il client genera un URL abbreviato come http://short.localhost/u/identificatore. Questo endpoint è una semplice richiesta GET che eseguirà il reindirizzamento HTTP effettivo sull'URL di destinazione.

Creiamo una tabella chiamata urls in MySQL con il seguente schema:

Nome Tipo
targetVARCHAR
idVARCHAR

target è l'URL originale mentre id è l'identificativo casuale associato all'URL.

Creiamo due funzioni helper per gestire l'autenticazione e la generazione della stringa casuale.


function is_authenticated( $key = 'auth', $value = 'secret') {
    return (isset($_POST[$key]) && $_POST[$key] === $value);
}

function id() {
    return uniqid();
}

Ora definiamo l'endpoint per restituire l'identificativo casuale al client. L'oggetto $db fa riferimento a qualsiasi driver/classe per MySQL.


require_once 'helpers.funcs.php';
require_once 'db.php';

header('Content-Type: application/json');

$output = [];

if(is_authenticated()) {
    $url = trim($_POST['url']);
    $dest = $db->query("SELECT * FROM urls WHERE target = '$url'");
    if($dest) {
        $output['id'] = $dest['id'];
    } else {
        $id = id();
        $db->query("INSERT INTO urls VALUES('$url','$id'));
        $output['id'] = $id;
    }
} else {
    header('HTTP/1.1 401 Unauthorized');
    $output['error'] = 'Unauthorized';
}

echo json_encode($output);
exit;

Inseriamo la logica di autenticazione all'interno di una funzione in modo che sia riutilizzabile su altri endpoint della nostra applicazione.

Ora un client ottiene la breve stringa di identificazione associata a quell'URL. Possiamo quindi implementare l'endpoint che gestisce il reindirizzamento HTTP.


require_once 'db.php';

$id = $_GET['id'];
$dest = $db->query("SELECT * FROM urls WHERE id = '$id'");

if($dest) {
    $target = $dest['target'];
    header("Location: $target");
} else {
   header('HTTP/1.1 404 Not Found'); 
}
exit;

Se l'URL è stato archiviato nella nostra tabella, proviamo a trovare una corrispondenza con la sua stringa di identificazione. Se c'è una corrispondenza, eseguiamo un reindirizzamento HTTP sull'URL di destinazione.

C'è un problema con la nostra soluzione che vale la pena menzionare: la nostra tabella prima o poi diventerà molto grande a causa del numero di record che vi verranno memorizzati.

Una possibile soluzione sarebbe quella di aggiungere un campo temporale al nostro schema in modo che possa essere utilizzato come riferimento per un'operazione batch periodica che rimuove i dati obsoleti o scaduti.

L'autore

Gabriele Romanato, sviluppatore web full stack specializzato in siti, applicativi web ed e-commerce con Node.js e PHP.