【PHP】現在のURLを取得する方法|$_SERVER・parse_url・WordPress対応

【PHP】現在のURLを取得する方法|$_SERVER・parse_url・WordPress対応 PHP

PHPで現在アクセスしているページのURLを取得したいとき、もっとも基本的な方法は $_SERVER 変数を使うことです。

しかし、プロトコル(HTTP / HTTPS)の判定、ポート番号の扱い、クエリ文字列の有無など、正確なURLを組み立てるには意外と考慮すべきポイントが多いのが実情です。

この記事では、$_SERVER による基本的な取得方法から、parse_url() によるURL分解、http_build_query() によるクエリ文字列の組み立て、WordPress関数、セキュリティ上の注意点、そして実務で頻出するパターン集まで、現在のURLに関する知識を網羅的に解説します。

この記事で学べること

  • $_SERVER変数で現在のURLを取得する基本
  • プロトコル・ホスト名・ポート・パス・クエリ文字列の個別取得
  • parse_url() でURLを分解する方法
  • http_build_query() でクエリ文字列を組み立てる方法
  • WordPress専用のURL取得関数
  • $_SERVERのセキュリティリスクと対策
  • 実務で使えるURL操作パターン集
スポンサーリンク
  1. $_SERVERで現在のURLを取得する基本
    1. もっともシンプルな方法
    2. HTTPS対応:プロトコルを自動判定する
    3. リバースプロキシ環境でのHTTPS判定
    4. ポート番号を含む完全なURLを取得する
  2. URLの各パーツを個別に取得する方法
    1. $_SERVER変数一覧テーブル
    2. 各パーツを個別に取得するコード例
    3. REQUEST_URI と PHP_SELF と SCRIPT_NAME の違い
  3. parse_url()でURLを分解する
    1. 基本的な使い方
    2. parse_url()が返すキー一覧
    3. 特定のパーツだけを取得する(第2引数)
    4. parse_url()で現在のURLを分解する実用例
    5. parse_url()の注意点
  4. http_build_query()でクエリ文字列を組み立てる
    1. 基本的な使い方
    2. 配列パラメータの扱い
    3. エンコーディングタイプの指定
    4. 現在のURLにクエリパラメータを追加・変更する
  5. WordPressでのURL取得方法
    1. サイトURL関連の関数
    2. 現在のページURLを取得する
    3. 現在アクセス中のURL(フロントエンド)
    4. URLのエスケープ(esc_url)
  6. セキュリティ上の注意点
    1. $_SERVERの値はユーザーが改ざん可能
    2. XSS攻撃の例
    3. SERVER_NAME vs HTTP_HOST の違い
    4. エスケープ関数の使い分け
  7. 実務でよく使うパターン集
    1. パターン1:リダイレクト先の組み立て
    2. パターン2:現在のページURLをフォームに埋め込む
    3. パターン3:canonicalタグの出力
    4. パターン4:ページネーションURLの生成
    5. パターン5:現在のURLが特定のパスか判定する
    6. パターン6:URLの正規化(末尾スラッシュの統一)
    7. パターン7:APIレスポンスに現在のURLを含める
  8. まとめ
  9. あわせて読みたい

$_SERVERで現在のURLを取得する基本

PHPで現在のURLを取得するもっとも一般的な方法は、スーパーグローバル変数 $_SERVER を使うことです。$_SERVER はWebサーバーが自動的にセットする連想配列で、リクエストに関するさまざまな情報が格納されています。

もっともシンプルな方法

現在のURLを取得するもっとも基本的なコードは次のとおりです。

PHP
// 現在のURLを取得する
$url = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

echo $url;
// 例: http://example.com/path/to/page?id=123

このコードは $_SERVER['HTTP_HOST'](ホスト名)と $_SERVER['REQUEST_URI'](パス+クエリ文字列)を連結して完全なURLを組み立てています。

注意:上の例ではプロトコルを http:// に固定していますが、実際のサイトではHTTPSかどうかを判定する必要があります。次のセクションで正しい方法を解説します。

HTTPS対応:プロトコルを自動判定する

現在のアクセスがHTTPなのかHTTPSなのかは、$_SERVER['HTTPS'] で判定できます。

PHP
// プロトコルを判定する
$scheme = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on')
    ? 'https'
    : 'http';

// 完全なURLを組み立てる
$url = $scheme . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

echo $url;
// 例: https://example.com/path/to/page?id=123

ポイント:$_SERVER['HTTPS'] はHTTPS接続時に 'on' がセットされます。HTTP接続時はキー自体が存在しないか、空文字列になります。そのため isset() で存在チェックを行いましょう。

リバースプロキシ環境でのHTTPS判定

ロードバランサーやCDN(CloudFlare等)を経由している場合、Webサーバーへのアクセス自体はHTTPで行われることがあります。この場合、$_SERVER['HTTPS'] だけでは正しく判定できません。

PHP
// リバースプロキシ対応のHTTPS判定
function isHttps(): bool
{
    // 1. 直接HTTPS接続
    if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') {
        return true;
    }

    // 2. リバースプロキシ経由(X-Forwarded-Proto ヘッダー)
    if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
        return true;
    }

    // 3. ポート番号で判定
    if (isset($_SERVER['SERVER_PORT']) && (int)$_SERVER['SERVER_PORT'] === 443) {
        return true;
    }

    return false;
}

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

ポート番号を含む完全なURLを取得する

開発環境や非標準ポートで動作するサーバーでは、ポート番号もURLに含める必要があります。

PHP
// ポート番号を含むURLの組み立て
function getCurrentUrl(): string
{
    $scheme = isHttps() ? 'https' : 'http';
    $host   = $_SERVER['HTTP_HOST'];
    $port   = (int)$_SERVER['SERVER_PORT'];
    $uri    = $_SERVER['REQUEST_URI'];

    // デフォルトポート(80, 443)の場合はポートを省略
    $portStr = '';
    if (($scheme === 'http' && $port !== 80) || ($scheme === 'https' && $port !== 443)) {
        // HTTP_HOST にポートが含まれていない場合のみ付与
        if (strpos($host, ':') === false) {
            $portStr = ':' . $port;
        }
    }

    return $scheme . '://' . $host . $portStr . $uri;
}

echo getCurrentUrl();
// 例: http://localhost:8080/myapp/index.php?page=1

ポイント:HTTP_HOST はブラウザが送信する Host ヘッダーの値で、ポート番号が含まれる場合があります(例: localhost:8080)。重複を避けるため、strpos() でコロンの有無をチェックしています。

URLの各パーツを個別に取得する方法

URLは複数のパーツで構成されています。以下のURLを例に、各パーツを $_SERVER でどう取得するか見ていきましょう。

URLの構造
https://example.com:8080/blog/article.php?id=123&page=2#section1
|____| |___________||___||_________________||_______________||______|
scheme    host       port     path           query string   fragment

$_SERVER変数一覧テーブル

URLに関連する $_SERVER の主要なキーを一覧にまとめます。

$_SERVER キー 取得できる値
HTTP_HOST ホスト名(Host ヘッダーの値) example.com
SERVER_NAME サーバー設定のホスト名 example.com
SERVER_PORT ポート番号 8080
REQUEST_URI パス+クエリ文字列 /blog/article.php?id=123&page=2
QUERY_STRING クエリ文字列のみ id=123&page=2
PHP_SELF 実行中スクリプトのパス /blog/article.php
SCRIPT_NAME スクリプトのパス(PATH_INFO除く) /blog/article.php
SCRIPT_FILENAME スクリプトの絶対パス /var/www/html/blog/article.php
PATH_INFO パスの追加情報 /extra/path
HTTPS HTTPS接続なら "on" on
REQUEST_SCHEME プロトコル(Apache 2.4+) https

各パーツを個別に取得するコード例

以下のコードで、URLの各パーツを個別に取得できます。

PHP
// アクセスURL: https://example.com:8080/blog/article.php?id=123&page=2

// プロトコル
$scheme = $_SERVER['REQUEST_SCHEME'] ?? 'http';
echo $scheme;  // "https"

// ホスト名
$host = $_SERVER['HTTP_HOST'];
echo $host;  // "example.com:8080"(ポート含む場合あり)

// サーバー名(ポートを含まない)
$serverName = $_SERVER['SERVER_NAME'];
echo $serverName;  // "example.com"

// ポート番号
$port = $_SERVER['SERVER_PORT'];
echo $port;  // "8080"

// パス+クエリ文字列
$requestUri = $_SERVER['REQUEST_URI'];
echo $requestUri;  // "/blog/article.php?id=123&page=2"

// クエリ文字列のみ
$query = $_SERVER['QUERY_STRING'];
echo $query;  // "id=123&page=2"

// スクリプトのパス(クエリ文字列なし)
$scriptName = $_SERVER['SCRIPT_NAME'];
echo $scriptName;  // "/blog/article.php"

// パスのみ(REQUEST_URIからクエリ文字列を除去)
$path = strtok($_SERVER['REQUEST_URI'], '?');
echo $path;  // "/blog/article.php"

REQUEST_URI と PHP_SELF と SCRIPT_NAME の違い

この3つは混同されやすいので、違いを整理しておきましょう。

変数 内容 クエリ文字列 PATH_INFO
REQUEST_URI リクエスト全体のURI 含む 含む
PHP_SELF スクリプトパス + PATH_INFO 含まない 含む
SCRIPT_NAME スクリプトパスのみ 含まない 含まない
PHP
// アクセスURL: /index.php/extra/path?key=value

echo $_SERVER['REQUEST_URI'];  // "/index.php/extra/path?key=value"
echo $_SERVER['PHP_SELF'];     // "/index.php/extra/path"
echo $_SERVER['SCRIPT_NAME']; // "/index.php"
echo $_SERVER['PATH_INFO'];    // "/extra/path"
echo $_SERVER['QUERY_STRING']; // "key=value"

使い分けのポイント:完全なURLを組み立てるなら REQUEST_URI、クエリ文字列なしのパスだけなら SCRIPT_NAME、パスの追加情報が必要なら PHP_SELF を使います。ただし PHP_SELF にはXSSリスクがあるので注意が必要です(セキュリティの章で詳しく解説します)。

parse_url()でURLを分解する

parse_url() はURLの文字列を受け取り、各パーツ(スキーム、ホスト、ポート、パス、クエリ、フラグメント)に分解して連想配列で返すPHP組み込み関数です。

$_SERVER 変数を組み合わせなくても、URLの文字列さえあれば簡単にパーツを取り出せます。

基本的な使い方

PHP
$url = 'https://example.com:8080/blog/article.php?id=123&page=2#section1';

$parsed = parse_url($url);

print_r($parsed);
実行結果
Array
(
    [scheme] => https
    [host] => example.com
    [port] => 8080
    [path] => /blog/article.php
    [query] => id=123&page=2
    [fragment] => section1
)

parse_url()が返すキー一覧

キー 内容
scheme プロトコル https
host ホスト名 example.com
port ポート番号(整数) 8080
user ユーザー名(Basic認証) admin
pass パスワード(Basic認証) secret
path パス /blog/article.php
query クエリ文字列(?の後) id=123&page=2
fragment フラグメント(#の後) section1

注意:parse_url() は存在しないパーツのキーは返しません。たとえばポート番号がないURLでは port キーが配列に含まれません。アクセス前に isset() や null合体演算子(??)でチェックしましょう。

特定のパーツだけを取得する(第2引数)

parse_url() の第2引数に定数を指定すると、特定のパーツだけを文字列(またはint)で直接取得できます。

PHP
$url = 'https://example.com/blog/article.php?id=123';

// 個別に取得
echo parse_url($url, PHP_URL_SCHEME);  // "https"
echo parse_url($url, PHP_URL_HOST);    // "example.com"
echo parse_url($url, PHP_URL_PORT);    // null(ポート未指定)
echo parse_url($url, PHP_URL_PATH);    // "/blog/article.php"
echo parse_url($url, PHP_URL_QUERY);   // "id=123"

parse_url()で現在のURLを分解する実用例

PHP
// 現在のURLを組み立ててから分解する
$currentUrl = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http')
    . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

$parts = parse_url($currentUrl);

// パスだけ取得
$path = $parts['path'] ?? '/';

// クエリ文字列を連想配列に変換
$queryParams = [];
if (isset($parts['query'])) {
    parse_str($parts['query'], $queryParams);
}

print_r($queryParams);
// Array ( [id] => 123 [page] => 2 )

ポイント:parse_str() はクエリ文字列を連想配列に変換する関数です。parse_url() と組み合わせることで、URLのクエリパラメータを簡単に操作できます。

parse_url()の注意点

parse_url() を使う際に知っておくべき注意点をまとめます。

注意点 詳細
URLのバリデーションではない parse_url() は構文チェックを行いません。不正なURLでもパースを試みます
相対URLは非推奨 相対パスを渡すと予期しない結果になることがあります。絶対URLを渡しましょう
フラグメントはサーバーに送信されない # 以降はブラウザ側でのみ使われるため、$_SERVER 経由では取得できません
日本語URLはエンコード済みで扱う マルチバイト文字を含むURLは urlencode() してから渡しましょう

http_build_query()でクエリ文字列を組み立てる

http_build_query() は連想配列からURLのクエリ文字列を生成する関数です。parse_url() / parse_str() と逆の操作を行います。

基本的な使い方

PHP
$params = [
    'category' => 'php',
    'page'     => 2,
    'sort'     => 'date',
];

$query = http_build_query($params);

echo $query;
// category=php&page=2&sort=date

配列パラメータの扱い

値に配列を含む場合、http_build_query() は自動的に key[0]=val1&key[1]=val2 形式にエンコードします。

PHP
$params = [
    'tags' => ['php', 'laravel', 'mysql'],
    'page' => 1,
];

echo http_build_query($params);
// tags%5B0%5D=php&tags%5B1%5D=laravel&tags%5B2%5D=mysql&page=1

// デコードすると: tags[0]=php&tags[1]=laravel&tags[2]=mysql&page=1

エンコーディングタイプの指定

第4引数でエンコーディングの形式を変更できます。

定数 セパレータ 用途
PHP_QUERY_RFC1738(デフォルト) & 一般的なURL用
PHP_QUERY_RFC3986 & RFC 3986準拠(スペースが%20になる)
PHP
$params = ['name' => '田中 太郎'];

// RFC 1738(デフォルト): スペースが + になる
echo http_build_query($params, '', '&', PHP_QUERY_RFC1738);
// name=%E7%94%B0%E4%B8%AD+%E5%A4%AA%E9%83%8E

// RFC 3986: スペースが %20 になる
echo http_build_query($params, '', '&', PHP_QUERY_RFC3986);
// name=%E7%94%B0%E4%B8%AD%20%E5%A4%AA%E9%83%8E

現在のURLにクエリパラメータを追加・変更する

parse_url() + parse_str() + http_build_query() を組み合わせると、現在のURLのクエリパラメータを柔軟に操作できます。

PHP
// 現在のURLのクエリパラメータを取得
$currentQuery = $_SERVER['QUERY_STRING'] ?? '';
parse_str($currentQuery, $params);

// パラメータを追加・変更
$params['page'] = 3;
$params['sort'] = 'popular';

// 不要なパラメータを削除
unset($params['debug']);

// URLを再構築
$newQuery = http_build_query($params);
$path = strtok($_SERVER['REQUEST_URI'], '?');
$newUrl = $path . '?' . $newQuery;

echo $newUrl;
// 例: /blog/article.php?id=123&page=3&sort=popular

実務でのコツ:クエリパラメータの操作は、ページネーション、フィルタ、ソートなどのUI実装で頻繁に使います。parse_str() + http_build_query() の組み合わせを覚えておくと、URLの組み立てがスムーズになります。

WordPressでのURL取得方法

WordPressには、URLを取得するための専用関数が豊富に用意されています。テーマやプラグインの開発では、$_SERVER を直接使うよりもこれらの関数を使うのが推奨されます。

サイトURL関連の関数

関数 戻り値 用途
home_url() サイトのトップページURL トップへのリンク生成
site_url() WordPressインストールURL wp-login.php等へのリンク
admin_url() 管理画面URL 管理画面へのリンク生成
content_url() wp-contentディレクトリURL アセットの参照
plugins_url() プラグインディレクトリURL プラグイン内のファイル参照
get_theme_file_uri() テーマファイルのURL テーマ内アセットの参照
PHP
// サイトURL関連
echo home_url();        // https://example.com
echo home_url('/about');  // https://example.com/about
echo site_url();        // https://example.com(通常はhome_urlと同じ)
echo admin_url();       // https://example.com/wp-admin/
echo content_url();     // https://example.com/wp-content

// パスを連結
echo home_url('/category/php/');  // https://example.com/category/php/
echo admin_url('edit.php');       // https://example.com/wp-admin/edit.php

現在のページURLを取得する

PHP
// 現在の投稿・固定ページのURL(ループ内)
echo get_permalink();   // https://example.com/blog/my-post/

// 投稿IDを指定してURLを取得
echo get_permalink(123);  // https://example.com/blog/post-123/

// カテゴリ・タグのアーカイブURL
echo get_category_link(5);  // https://example.com/category/php/
echo get_tag_link(10);      // https://example.com/tag/laravel/

// 著者アーカイブURL
echo get_author_posts_url(1);  // https://example.com/author/admin/

// カスタム投稿タイプのアーカイブURL
echo get_post_type_archive_link('product');  // https://example.com/product/

現在アクセス中のURL(フロントエンド)

WordPress関数で「現在ブラウザに表示されているURL」を取得する方法です。

PHP
// 方法1: グローバル変数を使う
global $wp;
$currentUrl = home_url(add_query_arg([], $wp->request));

// 方法2: $_SERVER を使う(WordPress推奨ではないが確実)
$currentUrl = (is_ssl() ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

// 方法3: add_query_arg() でクエリ付きURLを取得
$currentUrl = home_url(add_query_arg(NULL, NULL));

ポイント:WordPressでは is_ssl() 関数でHTTPS判定ができます。内部的にはリバースプロキシの X-Forwarded-Proto ヘッダーもチェックしてくれるため、$_SERVER['HTTPS'] を直接見るよりも確実です。

URLのエスケープ(esc_url)

WordPressではURLを出力する際に esc_url() でエスケープするのがセキュリティ上の必須ルールです。

PHP
// HTML出力時は必ず esc_url() を通す
$url = get_permalink();

// OK: エスケープ済み
echo '<a href="' . esc_url($url) . '">リンク</a>';

// NG: エスケープなし(XSSリスク)
echo '<a href="' . $url . '">リンク</a>';

// リダイレクトの場合は esc_url_raw() を使う
wp_redirect(esc_url_raw($url));
関数 用途 使用場面
esc_url() HTML出力用のエスケープ href属性、src属性など
esc_url_raw() DB保存・リダイレクト用 wp_redirect()、DB書き込み

セキュリティ上の注意点

$_SERVER 変数は便利ですが、セキュリティ上のリスクを正しく理解しておく必要があります。特にXSS(クロスサイトスクリプティング)攻撃の温床になりやすいため、出力時のエスケープは必須です。

$_SERVERの値はユーザーが改ざん可能

$_SERVER の値はすべてが安全なわけではありません。以下の変数は、クライアント(ブラウザ)から送信されたHTTPヘッダーに由来するため、攻撃者が自由に書き換えることができます。

変数 安全性 由来
HTTP_HOST 危険 クライアントのHostヘッダー
REQUEST_URI 危険 クライアントのリクエスト行
QUERY_STRING 危険 クライアントのリクエスト行
PHP_SELF 危険 リクエストURIから生成
HTTP_REFERER 危険 クライアントのRefererヘッダー
SERVER_NAME 比較的安全 サーバー設定(UseCanonicalName On時)
SCRIPT_NAME 比較的安全 サーバー側で決定
SCRIPT_FILENAME 比較的安全 サーバー側で決定

XSS攻撃の例

エスケープなしで $_SERVER['PHP_SELF'] を出力すると、XSS攻撃を受ける可能性があります。

PHP
// NG: XSS脆弱性のあるコード
echo '<form action="' . $_SERVER['PHP_SELF'] . '">';

// 攻撃者が以下のURLにアクセスさせると...
// /form.php/"><script>alert(document.cookie)</script>

// 出力されるHTML:
// <form action="/form.php/"><script>alert(document.cookie)</script>">
// → JavaScriptが実行される!
PHP
// OK: htmlspecialchars() でエスケープ
echo '<form action="' . htmlspecialchars($_SERVER['PHP_SELF'], ENT_QUOTES, 'UTF-8') . '">';

// OK: SCRIPT_NAME を使う(PATH_INFOを含まないので安全)
echo '<form action="' . htmlspecialchars($_SERVER['SCRIPT_NAME'], ENT_QUOTES, 'UTF-8') . '">';

// OK: WordPressの場合
echo '<form action="' . esc_url($_SERVER['REQUEST_URI']) . '">';

注意:$_SERVER の値をHTML内に出力する場合は、必ず htmlspecialchars()(またはWordPressの esc_url() / esc_attr())でエスケープしてください。これはURL取得に限らず、PHPセキュリティの基本中の基本です。

SERVER_NAME vs HTTP_HOST の違い

SERVER_NAMEHTTP_HOST は似ていますが、セキュリティ面で大きな違いがあります。

項目 SERVER_NAME HTTP_HOST
値の由来 サーバー設定(httpd.conf等) クライアントのHostヘッダー
改ざん可能性 低い(UseCanonicalName On時) 高い(攻撃者が変更可能)
ポート番号 含まない 含む場合がある
仮想ホスト対応 UseCanonicalName Off時のみ 常に対応
推奨用途 セキュリティ重視の場面 一般的なURL取得
PHP
// セキュリティ重視: ホワイトリストで検証
$allowedHosts = ['example.com', 'www.example.com'];
$host = $_SERVER['HTTP_HOST'];

if (!in_array($host, $allowedHosts, true)) {
    header('HTTP/1.1 400 Bad Request');
    exit('Invalid host');
}

$url = 'https://' . $host . $_SERVER['REQUEST_URI'];

ベストプラクティス:本番環境では、HTTP_HOST をそのまま信頼するのではなく、ホワイトリスト方式で許可するホスト名を限定しましょう。フレームワーク(Laravel、Symfony等)では、trusted_hosts の設定が組み込まれています。

エスケープ関数の使い分け

関数 用途 具体例
htmlspecialchars() HTML属性・本文への出力 <a href="…">
urlencode() URLクエリパラメータの値 ?name=…&age=…
rawurlencode() URLパスのエンコード /path/to/…
esc_url()(WP) HTML内のURL出力 href、src属性
esc_url_raw()(WP) DB保存・リダイレクト wp_redirect()
esc_attr()(WP) HTML属性値のエスケープ value属性等

実務でよく使うパターン集

ここからは、現在のURL取得に関連する実務で頻出するコードパターンを紹介します。コピー&ペーストして使えるようにまとめています。

パターン1:リダイレクト先の組み立て

ログイン後に元のページに戻すなど、リダイレクト先のURLを組み立てるパターンです。

PHP
// ログイン前のURLを保存してリダイレクト
$returnUrl = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http')
    . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

// ログインページにリダイレクト(戻り先をパラメータに含める)
$loginUrl = '/login.php?redirect=' . urlencode($returnUrl);
header('Location: ' . $loginUrl);
exit;

// --- ログイン処理後 ---
$redirect = filter_input(INPUT_GET, 'redirect', FILTER_VALIDATE_URL);

if ($redirect && parse_url($redirect, PHP_URL_HOST) === $_SERVER['SERVER_NAME']) {
    header('Location: ' . $redirect);
} else {
    header('Location: /');
}
exit;

注意:リダイレクト先URLは必ずバリデーションしましょう。外部サイトへのオープンリダイレクト攻撃を防ぐため、ホスト名が自サイトと一致するかチェックするのがベストプラクティスです。

パターン2:現在のページURLをフォームに埋め込む

お問い合わせフォームなどで、送信元のページURLをhiddenフィールドとして送信するパターンです。

PHP
$currentPage = htmlspecialchars(
    (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http')
    . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'],
    ENT_QUOTES,
    'UTF-8'
);
?>

<form method="post" action="/contact.php">
    <input type="hidden" name="source_url" value="<?= $currentPage ?>">
    <!-- 他のフォーム要素 -->
</form>

パターン3:canonicalタグの出力

SEO対策として、正規URLを <link rel="canonical"> タグで出力するパターンです。

PHP
// クエリ文字列を除いたcanonical URLを生成
$scheme = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http';
$host = $_SERVER['HTTP_HOST'];
$path = strtok($_SERVER['REQUEST_URI'], '?');

$canonical = $scheme . '://' . $host . $path;

echo '<link rel="canonical" href="' . htmlspecialchars($canonical, ENT_QUOTES, 'UTF-8') . '">';

// WordPress の場合
echo '<link rel="canonical" href="' . esc_url(get_permalink()) . '">';

パターン4:ページネーションURLの生成

一覧ページのページネーションリンクを生成するパターンです。

PHP
function buildPaginationUrl(int $page): string
{
    // 現在のクエリパラメータを取得
    $query = $_SERVER['QUERY_STRING'] ?? '';
    parse_str($query, $params);

    // ページ番号を設定
    if ($page <= 1) {
        unset($params['page']);
    } else {
        $params['page'] = $page;
    }

    // パスを取得(クエリ文字列除去)
    $path = strtok($_SERVER['REQUEST_URI'], '?');

    // URLを再構築
    if (empty($params)) {
        return $path;
    }

    return $path . '?' . http_build_query($params);
}

// 使用例
echo buildPaginationUrl(1);  // /articles.php?category=php
echo buildPaginationUrl(2);  // /articles.php?category=php&page=2
echo buildPaginationUrl(5);  // /articles.php?category=php&page=5

パターン5:現在のURLが特定のパスか判定する

ナビゲーションメニューでアクティブ状態を切り替えるなど、現在のURLが特定のパスと一致するか判定するパターンです。

PHP
function isCurrentPath(string $targetPath): bool
{
    $currentPath = strtok($_SERVER['REQUEST_URI'], '?');
    return rtrim($currentPath, '/') === rtrim($targetPath, '/');
}

function isCurrentPathPrefix(string $prefix): bool
{
    $currentPath = strtok($_SERVER['REQUEST_URI'], '?');
    return strpos($currentPath, $prefix) === 0;
}

// 使用例: ナビゲーションメニュー
?>
<nav>
    <a href="/blog/" class="<?= isCurrentPathPrefix('/blog') ? 'active' : '' ?>">ブログ</a>
    <a href="/about/" class="<?= isCurrentPath('/about') ? 'active' : '' ?>">会社概要</a>
    <a href="/contact/" class="<?= isCurrentPath('/contact') ? 'active' : '' ?>">お問い合わせ</a>
</nav>

パターン6:URLの正規化(末尾スラッシュの統一)

SEOやリダイレクトのために、URLの末尾スラッシュを統一するパターンです。

PHP
// 末尾にスラッシュを付与する(ディレクトリ風URL)
function enforceTrailingSlash(): void
{
    $uri = $_SERVER['REQUEST_URI'];
    $path = strtok($uri, '?');
    $query = $_SERVER['QUERY_STRING'] ?? '';

    // ファイル拡張子がないパスで、末尾スラッシュがない場合
    if ($path !== '/' && !preg_match('/\.[a-zA-Z0-9]+$/', $path) && substr($path, -1) !== '/') {
        $newUrl = $path . '/';
        if ($query !== '') {
            $newUrl .= '?' . $query;
        }
        header('Location: ' . $newUrl, true, 301);
        exit;
    }
}

パターン7:APIレスポンスに現在のURLを含める

REST APIで現在のエンドポイントURLやページネーションリンクを返すパターンです。

PHP
// REST APIレスポンスにページネーション情報を含める
function buildApiResponse(array $data, int $page, int $totalPages): array
{
    $baseUrl = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http')
        . '://' . $_SERVER['HTTP_HOST']
        . strtok($_SERVER['REQUEST_URI'], '?');

    $links = ['self' => $baseUrl . '?page=' . $page];

    if ($page > 1) {
        $links['prev'] = $baseUrl . '?page=' . ($page - 1);
    }
    if ($page < $totalPages) {
        $links['next'] = $baseUrl . '?page=' . ($page + 1);
    }

    return [
        'data'  => $data,
        'meta'  => ['page' => $page, 'total_pages' => $totalPages],
        'links' => $links,
    ];
}

// 使用例
header('Content-Type: application/json');
echo json_encode(buildApiResponse($items, 2, 10));
実行結果
{
    "data": [...],
    "meta": { "page": 2, "total_pages": 10 },
    "links": {
        "self": "https://example.com/api/articles?page=2",
        "prev": "https://example.com/api/articles?page=1",
        "next": "https://example.com/api/articles?page=3"
    }
}

まとめ

この記事では、PHPで現在のURLを取得する方法を基礎から実務パターンまで網羅的に解説しました。最後にポイントを整理します。

目的 推奨する方法
現在のURL(基本) $_SERVER['HTTP_HOST'] + $_SERVER['REQUEST_URI']
HTTPS判定 $_SERVER['HTTPS'] + HTTP_X_FORWARDED_PROTO
パスのみ取得 strtok($_SERVER['REQUEST_URI'], '?') or SCRIPT_NAME
クエリ文字列のみ $_SERVER['QUERY_STRING']
URLを分解 parse_url()
クエリの組み立て http_build_query()
WordPress home_url() / get_permalink() / is_ssl()
出力時のエスケープ htmlspecialchars() / esc_url()(WP)

この記事のポイント

  • $_SERVER['HTTP_HOST'] + $_SERVER['REQUEST_URI'] で現在の完全なURLを組み立てられる
  • HTTPS判定は $_SERVER['HTTPS'] だけでなく、リバースプロキシのヘッダーも考慮する
  • parse_url() でURLを分解、http_build_query() でクエリを組み立てる
  • WordPressでは home_url() / get_permalink() / is_ssl() を使う
  • $_SERVER の値はユーザーが改ざん可能なので、出力時は必ずエスケープする
  • 実務ではリダイレクト・canonical・ページネーションなどのパターンを押さえておく

あわせて読みたい