How to Get the Full URL in PHP Without Losing Your Mind?
\n\nEvery PHP developer has faced the task at least once: "How do I get the full URL of the current page?" It seems simple enough — just take $_SERVER['HTTP_HOST'], add $_SERVER['REQUEST_URI'] — and you're done. But reality, as always, throws in its own twists. HTTP or HTTPS? What about a non-standard port? What if the site is behind a proxy? What if you need not just to get it, but to do it quickly, without memory leaks, and with future-proofing?
The question "Get the full URL in PHP" on Stack Overflow has thousands of views and dozens of answers. This is no coincidence: the topic seems simple, but it's full of hidden pitfalls. Today we'll break down not just "how to do it", but how to do it correctly, quickly, and reliably. Let's go!
\n\nWhy is simple copying from $_SERVER a bad idea?
\n\nBeginner developers often write this:
\n\n$url = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];\n\nAt first glance, it works. But let's look at the problems:
\n- \n
- No HTTPS. If the site runs on HTTPS, you'll get
http://— and the browser will complain about mixed content. \n - Port. If the port is non-standard (e.g., 8080), it will be lost if you don't use
$_SERVER['SERVER_PORT']. \n - Proxies and load balancers. Behind a reverse proxy (Nginx, Cloudflare),
$_SERVER['HTTP_HOST']may not be what the user sees. \n - Security. The
HTTP_HOSTvalue can be manipulated by an attacker (Host header injection). \n
In short, copy-pasting from the first Stack Overflow answer is not the best option. Let's write a correct and performant function.
\n\nThe Reference Function: Getting the Full URL Correctly
\n\nHere is a reliable function that handles all the main scenarios:
\n\nfunction getFullUrl(): string {\n $protocol = 'http';\n if (\n (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')\n || (int)$_SERVER['SERVER_PORT'] === 443\n ) {\n $protocol = 'https';\n }\n\n // Consider headers from proxy (if trusted)\n $host = $_SERVER['HTTP_HOST'] ?? '';\n if (empty($host) && !empty($_SERVER['SERVER_NAME'])) {\n $host = $_SERVER['SERVER_NAME'];\n }\n\n // Port check\n $port = (int)$_SERVER['SERVER_PORT'];\n $portSuffix = '';\n if (\n ($protocol === 'http' && $port !== 80)\n || ($protocol === 'https' && $port !== 443)\n ) {\n $portSuffix = ':' . $port;\n }\n\n $uri = $_SERVER['REQUEST_URI'] ?? '/';\n\n return $protocol . '://' . $host . $portSuffix . $uri;\n}\n\nWhat's important here?
\n- \n
- We check
HTTPS— the standard method, works in 99% of cases. \n - We account for
SERVER_PORT— if the site is on a non-standard port, we don't lose it. \n - A fallback via
SERVER_NAME— in caseHTTP_HOSTis empty. \n - We don't use
$_SERVER['SCRIPT_URI']— it's not available everywhere. \n
Performance Optimization: When Every Millisecond Counts
\n\nIf you call this function on every page or in a loop, it's worth thinking about speed. Here are a few techniques:
\n\n1. Caching the Result
\nIf the URL doesn't change within a single request (and it doesn't), cache it:
\n\nfunction getFullUrlCached(): string {\n static $url = null;\n if ($url === null) {\n $url = getFullUrl(); // use our function above\n }\n return $url;\n}\n\nA static variable retains the value after the first call — no repeated calculations.
\n\n2. Avoid Unnecessary Operations
\nDon't use filt