URL complet en PHP : comment l'obtenir rapidement et sans erreurs

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Obtenir l'URL complète en PHP : comment ne pas réinventer la roue et ne pas perdre en performance

\n\n

Tout développeur PHP se heurte tôt ou tard à cette question : « Comment obtenir l'URL complète de la page actuelle ? ». Cela semble simple : prenez $_SERVER['REQUEST_URI'], ajoutez le domaine, et le tour est joué. Mais le diable se cache dans les détails. La question « Get the full URL in PHP » sur Stack Overflow a recueilli des milliers de vues et des dizaines de réponses. Et ce n'est pas un hasard.

\n\n

Dans cet article, nous allons voir comment obtenir l'URL complète en PHP correctement, rapidement et sans bugs. Vous découvrirez la différence entre HTTP_HOST et SERVER_NAME, comment déterminer correctement le protocole (HTTPS ou HTTP), et pourquoi il ne faut pas copier aveuglément du code trouvé sur Internet. C'est parti !

\n\n

Pourquoi la méthode simple n'est-elle pas toujours la meilleure ?

\n\n

La solution la plus évidente ressemble à ceci :

\n\n
<?php\n$fullUrl = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];\n?>
\n\n

Ce code fonctionne, mais seulement si vous avez :

\n
    \n
  • Impérativement HTTP (pas HTTPS)
  • \n
  • Pas de port différent de 80 ou 443
  • \n
  • Un serveur qui transmet correctement l'en-tête Host
  • \n
\n\n

Dans le monde réel, ces conditions ne sont pas toujours remplies. Si le site fonctionne en HTTPS, vous obtiendrez une URL avec http://, ce qui entraînera une erreur de contenu mixte dans le navigateur. Si le port est non standard (par exemple 8080), il sera perdu. Et si un attaquant falsifie l'en-tête Host, vous pourriez obtenir une URL pointant vers un domaine étranger.

\n\n

Composants d'une URL complète : analyse détaillée

\n\n

Avant d'écrire une solution universelle, rappelons de quoi se compose une URL complète :

\n\n
scheme://host:port/path?query#fragment
\n\n

En PHP, les éléments suivants sont disponibles dans le tableau superglobal $_SERVER :

\n
    \n
  • scheme — le protocole (HTTP ou HTTPS). Il n'y a pas de clé directe, mais on peut le déterminer via $_SERVER['HTTPS'] ou $_SERVER['REQUEST_SCHEME'] (disponible depuis PHP 7.4).
  • \n
  • host — le domaine. Deux candidats : HTTP_HOST (issu de l'en-tête Host) et SERVER_NAME (issu de la configuration du serveur).
  • \n
  • port — le port. $_SERVER['SERVER_PORT']. Si le port est standard (80 pour HTTP, 443 pour HTTPS), on peut l'omettre.
  • \n
  • path — le chemin. $_SERVER['REQUEST_URI'] contient le chemin et la chaîne de requête.
  • \n
  • query — la chaîne de requête. On peut l'obtenir séparément via $_SERVER['QUERY_STRING'].
  • \n
  • fragment — l'ancre. Elle n'est pas transmise au serveur, donc impossible à obtenir.
  • \n
\n\n

La solution correcte : la fonction getFullUrl()

\n\n

Voici une méthode fiable et performante pour obtenir l'URL complète en PHP :

\n\n
<?php\nfunction getFullUrl(): string {\n    // Déterminer le protocole\n    $scheme = 'http';\n    if (\n        (isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] === 'on' || $_SERVER['HTTPS'] === '1'))\n        || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https')\n    ) {\n        $scheme = 'https';\n    }\n\n    // Hôte : privilégier HTTP_HOST, mais vérifier qu'il n'est pas vide\n    $host = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'] ?? 'localhost';\n\n    // Port : ajouter uniquement s'il est non standard\n    $port = (int) ($_SERVER['SERVER_PORT'] ?? 80);\n    $portStr = '';\n    if (\n        ($scheme === 'http' && $port !== 80) ||\n        ($scheme === 'https' && $port !== 443)\n    ) {\n        $portStr = ':' . $port;\n    }\n\n    // URI\n    $uri = $_SERVER['REQUEST_URI'] ?? '/';\n\n    return $scheme . '://' . $host . $portStr . $uri;\n}\n?>
\n\n

Cette fonction prend en compte :

\n
    \n
  • Le protocole HTTPS (y compris via des serveurs proxy avec l'en-tête X-Forwarded-Proto).
  • \n
  • Les ports non standard.
  • \

Blogs

Book Recommendations