← All posts

Getting current page URL using PHP

· PHP

First appeared on mobifreaks.com · Updated

This was one of my first tutorials. I wrote it on Mobifreaks in 2011 and shared a shorter version on munwr.com in 2014. The idea still works, but the code needed fixing, so here is the original and what I would write today.

The two building blocks

PHP keeps details about the current request in the $_SERVER array. Two of its keys give you most of a URL:

  • $_SERVER['HTTP_HOST'] is the host name, like www.example.com.
  • $_SERVER['REQUEST_URI'] is the path and query string, like /2011/04/html-introduction?ref=home.

Join them with a scheme in front and you have the full URL.

The 2011 version

<?php
$Get_url = "http://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
echo $Get_url;
?>

In 2014 I shortened it to $get-url = ..., which is worse: PHP variable names can't contain a hyphen, so that line is a syntax error.

Both versions also have two real problems:

  • They assume http://. Most sites are served over HTTPS now.
  • They are unsafe to echo as is. HTTP_HOST and REQUEST_URI come from the request, so a visitor can put markup in them.

What I would write today

<?php
$isHttps = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
    || (int) ($_SERVER['SERVER_PORT'] ?? 0) === 443;

$currentUrl = ($isHttps ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
?>

<a href="<?= htmlspecialchars($currentUrl, ENT_QUOTES) ?>">Permalink</a>
  • $_SERVER['HTTPS'] is set to a non-empty value on HTTPS requests. IIS sets it to off on plain HTTP, hence the extra check.
  • htmlspecialchars() escapes the URL before it goes into your HTML.

Behind a proxy or load balancer

If a proxy (Cloudflare, a load balancer, a container platform) handles HTTPS for you, PHP sees plain HTTP. The proxy usually passes the original scheme in an X-Forwarded-Proto header. Only trust that header when your own proxy sets it, because anyone can send it.

Using a framework?

Let it do the work. It already handles proxies and schemes:

  • Laravel: url()->current() (without the query string) or url()->full() (with it).
  • Symfony: $request->getUri().