【PHP】現在のURLを取得する方法!$_SERVER変数の正しい組み合わせ

【PHP】現在のURLを取得する方法!$_SERVER変数の正しい組み合わせ PHP

どうも、kazuです。

Web系のスタートアップでエンジニアをしています。
SES時代から数えきれないほどの現場を見てきましたが、URLの取得といった基本的な処理ひとつとっても、エンジニアの「丁寧さ」や「リスク管理の意識」の差がはっきり出るなと感じているんですよ。

「とりあえず動けばいい」とネットの断片的なコードをコピペして、本番環境のHTTPS化やリバースプロキシ構成でバグを出す……。
そんな新人を何人も見てきました。

エンジニアの世界は厳しいものです。
常に「どんな環境でも正しく動くか」を突き詰めるストイックさが必要なんです。

今回は、PHPで現在のURLを取得するための、最も正確で効率的な方法を共有します。

【執筆者の簡易プロフィール】
kazu 執筆者:kazu
  • 38歳男性、既婚
  • Webエンジニア
  • 新卒でSESに入社し、Web系企業に常駐、その後Web系スタートアップに転職
  • 主な使用言語はRuby、PHP、JavaScript、HTML/CSS
  • モットーは「人に厳しく、自分にはもっと厳しく」

基本的な要素:$_SERVER変数の役割を理解すべき

PHPで現在のURLを構成するには、$_SERVER というスーパーグローバル変数に格納された情報を組み合わせる必要があります。

まずは、よく使う3つの要素を正確に把握しておきましょう。

// 1. ドメイン(ホスト)名を取得
echo $_SERVER['HTTP_HOST']; // 例: engineer-method.com

// 2. ドメイン以下のパスとクエリ文字列を取得
echo $_SERVER['REQUEST_URI']; // 例: /category/php?id=123

// 3. アクセスしているプロトコルを確認
echo $_SERVER['HTTPS']; // HTTPSなら 'on'、それ以外は空か 'off'

HTTP_HOST は「どこにアクセスしているか」というドメイン名、REQUEST_URI は「そのドメインの中のどのページか」という詳細な場所を示します。

これらを単純に繋げればURLになりますが、そのままでは「http」なのか「https」なのかが分かりません。
プロトコルを動的に判定して付け加えるのが、現場で求められる最低限の作法です。

現場で通用する「フルURL取得」の堅牢なコード

では、実際にどんな環境でも使い回せる「決定版」のコードを紹介します。
これを関数として定義しておけば、開発効率も上がりますし、何よりコードがスッキリします。

function getCurrentUrl() {
// 1. プロトコルの判定

$protocol = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') ? "https" : "http";

// 2. ホスト名の取得
$host = $_SERVER['HTTP_HOST'];

// 3. URI(パスとクエリ)の取得
$uri = $_SERVER['REQUEST_URI'];

// 4. 全てを連結して返す
return $protocol . "://" . $host . $uri;

}

// 使用例
echo getCurrentUrl();

コードの内容を説明します。

まず三項演算子を使って、$_SERVER[‘HTTPS’] が ‘on’ かどうかをチェックしています。
今の時代、常時SSL(HTTPS)が当たり前ですが、ローカルの開発環境ではHTTPであることも多いので、この分岐は必須なんですよ。

そして、それらを文字列結合で一つにまとめます。
「ただこれだけ?」と思うかもしれませんが、これを毎回手書きしているようでは効率が悪すぎます。

共通関数(ヘルパー関数)として定義しておくのが、プロのエンジニアの流儀ですね。

【注意】ポート番号やリバースプロキシの罠を考慮せよ

スタートアップの現場では、Dockerを使ったり、ロードバランサーの後ろにPHPサーバーを置いたりすることがよくあります。

その場合、通常の HTTP_HOST だけではポート番号が取れなかったり、プロトコル判定が狂ったりすることがあるんです。

もし 8080 などの標準外ポートを使っている場合は、以下のような考慮が必要になるケースがあります。

// ポート番号が標準(80/443)以外の場合に付与する例
$port = $_SERVER['SERVER_PORT'];
$port_suffix = (($protocol === 'http' && $port == 80) || ($protocol === 'https' && $port == 443)) ? '' : ":$port";

// URL連結時に $host の代わりに $host$port_suffix を使う

特殊なネットワーク構成では、$_SERVER[‘SERVER_PORT’] を参照してポート番号を明示的に付け加える必要があります。

また、プロキシを経由している場合は HTTP_X_FORWARDED_PROTO を見なければならないこともあります。

「自分の環境では動く」で満足せず、インフラ構成まで意識してコードを書く。
これができるエンジニアこそが、現場で信頼されるんですよ。

セキュリティ:URLを出力する際は必ずサニタイズすべきです

これが最も重要な点かもしれません。
取得したURLを echo などでHTMLに出力する場合、絶対にそのまま出してはいけません。

// 危険な例
echo '<a href="' . getCurrentUrl() . '">リンク</a>';

// 安全な例(必ずエスケープする)
echo '<a href="' . htmlspecialchars(getCurrentUrl(), ENT_QUOTES, 'UTF-8') . '">リンク</a>';

コードの意味を説明します。

$_SERVER 変数はユーザー(クライアント)側から操作される可能性があるため、悪意のあるスクリプトを仕込まれる「XSS(クロスサイトスクリプティング)」の脆弱性になり得ます。

「外部からの入力値($_SERVERを含む)は、出力時に必ず無害化する」。
この鉄則を破る人間は、エンジニアを名乗る資格はないと僕は思います。

自分にも他人にも厳しく、安全なコードを徹底してください。

まとめ|保守性を考えて手法を選ぼう

PHPで現在のURLを取得する方法をまとめます。

・$_SERVER[‘HTTP_HOST’] と REQUEST_URI を組み合わせるのが基本。
・HTTPSかHTTPかを動的に判定するロジックを必ず入れる。
・環境(ポート番号やプロキシ)に応じた柔軟な設計を心掛ける。
・出力時は htmlspecialchars でのサニタイズを徹底する。

たかがURLの取得ですが、こうした基礎の積み重ねがシステムの品質と、エンジニアとしての価値を決めます。

妥協せず、常に最善の効率と安全性を追求し続けてください。
その努力の先にしか、本当のプロフェッショナルな世界はありませんから。

さて、サクッと実装が終わったら、次のタスクに向けて頭を冷やしましょうか。

以上、kazuでした。

コメント

タイトルとURLをコピーしました