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操作パターン集
$_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_NAME と HTTP_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・ページネーションなどのパターンを押さえておく
あわせて読みたい