HOWTO · PHP

Retour à la page précédente en PHP

Ce tutoriel présente comment revenir à la page précédente en PHP

Sur cette page

Pour renvoyer un visiteur vers la page qui contient un formulaire, lisez la valeur facultative HTTP_REFERER dans $_SERVER, n’acceptez qu’une destination locale autorisée et envoyez un en-tête Location avec header() avant de produire une réponse. Le référent n’est pas toujours présent : prévoyez donc une destination locale de secours sûre.

Utiliser l’en-tête de requête HTTP_REFERER pour revenir à la page précédente en PHP

Un formulaire sur index.php peut envoyer ses données à un gestionnaire tel que home.php. Le navigateur peut transmettre l’URL de la page contenant le formulaire dans l’en-tête de requête HTTP_REFERER, que PHP expose dans $_SERVER['HTTP_REFERER']. Les navigateurs et les paramètres de confidentialité peuvent omettre cet en-tête, et les clients peuvent fournir n’importe quelle valeur : ne l’utilisez donc pas pour une redirection sans la valider. Cet en-tête est une indication incluse dans la requête, pas un historique fiable de la navigation. L’application doit continuer à fonctionner lorsqu’il est absent.

Dans index.php, le formulaire peut envoyer un message avec les données soumises :

<form action="home.php" method="post"><input type="hidden" name="message" value="Saved."><button type="submit">Submit</button></form>

Le gestionnaire home.php complet ci-dessous n’accepte que le chemin local /index.php. Cet exemple nécessite PHP 8.0 ou une version ultérieure, car il utilise str_contains(). Il conserve les paramètres de requête déjà présents sur cette page, ajoute le message soumis et utilise /index.php comme destination de secours si le référent est absent ou pointe ailleurs. Lorsqu’il est exécuté en ligne de commande, il utilise une requête d’exemple et affiche la cible de redirection, ce qui permet de suivre le chemin de réussite local. Pour une requête Web, il envoie une redirection 303, puis termine l’exécution.

<?php
// home.php
$isCli = PHP_SAPI === 'cli';

// Provide a sample request when running this file directly with PHP CLI.
if ($isCli) {
    $_SERVER['REQUEST_METHOD'] = 'POST';
    $_SERVER['HTTP_REFERER'] = 'https://example.test/index.php?tab=profile';
    $_POST['message'] = 'Saved.';
}

if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
    http_response_code(405);
    exit;
}

$message = $_POST['message'] ?? 'Your form was submitted.';
if (!is_string($message)) {
    $message = 'Your form was submitted.';
}

$destination = '/index.php';
$referrer = $_SERVER['HTTP_REFERER'] ?? '';
$parts = parse_url($referrer);
if (is_array($parts) && ($parts['path'] ?? '') === '/index.php') {
    $query = [];
    parse_str($parts['query'] ?? '', $query);
    $destination = '/index.php';
    if ($query !== []) {
        $destination .= '?' . http_build_query($query);
    }
}

$separator = str_contains($destination, '?') ? '&' : '?';
$target = $destination . $separator . http_build_query(['message' => $message]);

if ($isCli) {
    echo $target, PHP_EOL;
    exit;
}

header('Location: ' . $target, true, 303);
exit;

Pour la requête d’exemple, le gestionnaire affiche cette cible de redirection :

/index.php?tab=profile&message=Saved.

Sur la page de retour, échappez le message avant de l’insérer dans le HTML. Vérifiez d’abord que la valeur du paramètre est une chaîne, car les paramètres de requête peuvent aussi arriver sous forme de tableaux : htmlspecialchars(is_string($_GET['message'] ?? null) ? $_GET['message'] : '', ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'). L’encodage d’URL effectué par le gestionnaire protège le paramètre de requête ; l’échappement HTML lors de l’affichage protège la page. Effectuez la même vérification de type pour toute autre valeur transmise à une fonction d’échappement qui attend une chaîne.

Le gestionnaire reconstruit la destination à partir du chemin local autorisé au lieu d’utiliser l’hôte indiqué par le référent ; une URL externe ne peut donc pas devenir la cible de redirection. La liste des chemins autorisés est volontairement restreinte. Si votre application comporte plusieurs pages avec des formulaires, indiquez explicitement chaque chemin local accepté et prévoyez une destination locale de secours sûre pour les autres valeurs. L’exemple conserve les paramètres de requête du référent accepté, puis ajoute ou remplace le paramètre message avec http_build_query(). Cela évite de construire l’encodage d’URL à la main et sépare le chemin de redirection de sa chaîne de requête.

header() doit être appelé avant tout contenu HTML, espace blanc ou autre sortie de la réponse. Le exit qui suit la redirection empêche le reste du gestionnaire de s’exécuter comme si la requête s’était poursuivie normalement. Le code d’état 303 indique au navigateur de suivre la redirection avec une requête GET après l’envoi du formulaire en POST. La branche CLI sert uniquement à illustrer le comportement : dans une requête Web, PHP envoie l’en-tête de réponse au lieu d’afficher la cible dans le contenu de la page. Si votre environnement d’hébergement utilise une version antérieure de PHP, remplacez str_contains($destination, '?') par une vérification compatible, par exemple strpos($destination, '?') !== false, et vérifiez que le reste de l’application prend en charge cette version.