URL completo en PHP: cómo obtenerlo rápido y sin errores

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Obtener la URL completa en PHP: cómo no reinventar la rueda y no perder rendimiento

\n\n

Todo desarrollador PHP, tarde o temprano, se enfrenta a la pregunta: «¿Cómo obtengo la URL completa de la página actual?». Parece sencillo: tomas $_SERVER['REQUEST_URI'], le agregas el dominio y listo. Pero el diablo, como siempre, está en los detalles. La pregunta «Obtener la URL completa en PHP» en Stack Overflow ha acumulado miles de visitas y decenas de respuestas. Y no es casualidad.

\n\n

En este artículo analizaremos cómo obtener la URL completa en PHP de forma correcta, rápida y sin errores. Descubrirás la diferencia entre HTTP_HOST y SERVER_NAME, cómo determinar correctamente el protocolo (HTTPS o HTTP), y por qué no debes copiar código ciegamente de internet. ¡Allá vamos!

\n\n

¿Por qué la forma simple no siempre es la mejor?

\n\n

La opción más obvia se ve así:

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

Este código funciona, pero solo si tienes:

\n
    \n
  • Obligatoriamente HTTP (no HTTPS)
  • \n
  • Un puerto estándar (80 o 443)
  • \n
  • Un servidor que transmita correctamente la cabecera Host
  • \n
\n\n

En el mundo real, estas condiciones no siempre se cumplen. Si el sitio funciona con HTTPS, obtendrás una URL con http://, lo que generará un error de contenido mixto en el navegador. Si el puerto no es estándar (por ejemplo, 8080), se perderá. Y si un atacante falsifica la cabecera Host, podrías obtener una URL de un dominio ajeno.

\n\n

Componentes de la URL completa: análisis detallado

\n\n

Antes de escribir una solución universal, recordemos de qué se compone una URL completa:

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

En PHP, tenemos acceso a los siguientes elementos del array superglobal $_SERVER:

\n
    \n
  • scheme — protocolo (HTTP o HTTPS). No hay una clave directa, pero se puede determinar mediante $_SERVER['HTTPS'] o $_SERVER['REQUEST_SCHEME'] (disponible desde PHP 7.4).
  • \n
  • host — dominio. Hay dos candidatos: HTTP_HOST (de la cabecera Host) y SERVER_NAME (de la configuración del servidor).
  • \n
  • port — puerto. $_SERVER['SERVER_PORT']. Si el puerto es estándar (80 para HTTP, 443 para HTTPS), se puede omitir.
  • \n
  • path — ruta. $_SERVER['REQUEST_URI'] contiene la ruta y la cadena de consulta.
  • \n
  • query — cadena de consulta. Se puede obtener por separado con $_SERVER['QUERY_STRING'].
  • \n
  • fragment — ancla. No se envía al servidor, por lo que no se puede obtener.
  • \n
\n\n

Solución correcta: la función getFullUrl()

\n\n

Aquí tienes una forma fiable y eficiente de obtener la URL completa en PHP:

\n\n
<?php\nfunction getFullUrl(): string {\n    // Determinamos el protocolo\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    // Host: preferimos HTTP_HOST, pero verificamos que no esté vacío\n    $host = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'] ?? 'localhost';\n\n    // Puerto: solo lo agregamos si no es estándar\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

Esta función tiene en cuenta:

\n
    \n
  • El protocolo HTTPS (incluso a través de servidores proxy con la cabecera X-Forwarded-Proto).
  • \n
  • Puertos no estándar.
  • \n

Blogs

Book Recommendations