URLの絶対パスを相対パスに変換する複数の方法を紹介します。
なおWordPressにはget_permalink
関数やthe_permalink
, home_url
等の絶対URLを求める関数は存在しますが、相対URLを取得するための関数が存在しません。またPHPの環境変数$_SERVER['REQUEST_URI']
にはリクエストパラメータが含まれる場合があります。
// 絶対パスが求められてしまう
echo get_permalink(); // "http://marycore.jp/wp/index.php"
// GETパラメータが含まれてしまう
echo $_SERVER['REQUEST_URI']; // "/wp/index.php?amp=1"
特定のURLからドメイン名やスキーマ名、GETパラメータを含まない相対的なURL(/wp/index.php
などのサイトルート相対パス)を取得したい場合には、専用の関数で絶対パスを相対パスに変換するか、自前で処理を行う必要があります。
絶対パスから相対パスを取得・変換する複数の方法
PHPの標準関数としてはparse_url
が利用できます。WordPressではwp_make_link_relative
が用意されています。それぞれ一長一短があるため、用途に応じて使い分ける必要があります。
- parse_url関数による相対URLの抽出(明確な方法)
- wp_make_link_relative関数による相対URLの抽出(WordPressで利用可能)
- 文字列置換で相対URLへ変換(よく知られている方法)
- 相対URLの部分抽出(高速で汎用的)
parse_url関数による相対URLの抽出
parse_urlを用いる方法もありますが、パスの値によっては挙動に注意が必要になります。第二引数にPHP_URL_PATH
を指定した形で用いるようにします。?amp=1
などのGETパラメータは含まれなくなるため注意が必要です。
$url = "http://marycore.jp/wp/index.php";
parse_url($url, PHP_URL_PATH); // "/wp/index.php"
parse_url($url)['path']; // "/wp/index.php"
parse_url($url); // {scheme: "http", host: "marycore.jp", path: "/wp/index.php"}
parse_url('http://marycore.jp/?amp=1'); // {scheme: "http", host: "marycore.jp", path: "/", query: "amp=1"}
parse_url('http://marycore.jp/')['path']; // "/"
parse_url('http://marycore.jp')['path']; // Notice: Undefined index: path
parse_url('http://marycore.jp', PHP_URL_PATH); // NULL
parse_url('http://marycore.jp', PHP_URL_PATH) ?: '/'; // "/"
parse_url(false, PHP_URL_PATH); // ""
parse_url(null); // [path: ""]
parse_url(''); // [path: ""]
parse_url('Shop'); // [path: "Shop"]
parse_url(99); // [path: "99"]
wp_make_link_relative関数による相対URLの抽出
WordPressのwp_make_link_relative
関数はURLのフルパスからスキーム名とドメイン名を取り除いた値を返します。GETパラメータは含まれたままになるため注意してください。
wp_make_link_relative('http://marycore.jp/a.php?amp=1'); // "/a.php?amp=1"
wp_make_link_relative('http://marycore.jp/a.php'); // "/a.php"
wp_make_link_relative('http://marycore.jp/'); // "/"
wp_make_link_relative('http://marycore.jp'); // ""
wp_make_link_relative('http://marycore.jp') ?: '/'; // "/"
wp_make_link_relative(''); // ""
wp_make_link_relative(false); // ""
wp_make_link_relative(['http://marycore.jp/a', 'http://marycore.jp/b']); // ["a", "b"]
サーバー変数 $_SERVER['REQUEST_URI'] で相対URLを取得
環境変数REQUEST_URI
でページアクセス時のURIを取得することができます。ただしGETパラメータ/クエリストリングを含めたパスとなるため注意が必要です。またリクエスト方法によっては絶対パスが返される場合もあります。
// リクエストURL; http://marycore.jp/wp/index.php?amp=1#id
$_SERVER['REQUEST_URI']; // "/wp/index.php?amp=1"
先程紹介したparse_url関数を用いれば、ベースURLやGETパラメータを取り除いたパスを抽出することもできますが、parse_urlは相対URLの入力を正式にはサポートしていないため注意が必要です(PHP 7 現在)。
サーバーによってはREDIRECT_URL
という環境変数が存在しますが、利用用途が異なるため注意が必要です。
文字列置換で相対URLへ変換
よく知られている方法としては、絶対パスに含まれるベースURLを空文字で置き換える方法などがあります。
$base = "http://marycore.jp"; // ベースURL
$url = "http://marycore.jp/wp/index.php"; // 絶対URL
$s = str_replace($base, '', $url);
$s; // "/wp/index.php"
絶対パスがベースURLと同一の場合には空文字が返されるため注意してください。
$base = "http://marycore.jp";
str_replace($base, '', $base); // ""(空文字)
/* 対応策1 */ substr($base, strlen($base)) ?: '/' // 次項で紹介
/* 対応策2 */ $base == $base ? '/' : str_replace($base, '', $base);
WordPressの場合はhome_url
関数でベースURL、get_permalink
関数で現在の投稿のURLを取得することができます。
str_replace(home_url(), '', get_permalink());
// home_url() // "http://marycore.jp"
// get_permalink() // "http://marycore.jp/wp/index.php"
なおWordPressのget_permalink
が失敗した場合にはfalse
が返されるため、結果的にベースURLが求められてしまうという問題もあります。
// get_permalink() // ページが見つからなかった場合にはfalseが返される
str_replace(false, '', home_url()); // "http://marycore.jp"(絶対URL)
また、WordPress以外のフレームワークでベースURLを取得する際には、末尾の/
を取り除かなければならない場合があるため注意してください。rtrim
関数で末尾のスラッシュを取り除くことができます。
$s = Uri::base(false): // "http://marycore.jp/"
$s = rtrim($s, '/'); // "http://marycore.jp"
// Uri::current() == "http://marycore.jp/controller/method"
$t = str_replace(rtrim(Uri::base(false), '/'), '', Uri::current());
$t; // "/controller/method"
// より面白い方法
'/' . join(Uri::segments(), '/'); // "/controller/method"
相対URLの部分抽出
絶対URLに対して部分文字列の抽出を行うことで相対URLを取得することができます。
$base = "http://marycore.jp"; // ベースURL
$url = "http://marycore.jp/wp/index.php"; // 絶対URL
substr($url, strlen($base)); // "/wp/index.php"
// 想定外の値に対処する方法(失敗時には`/notice`が返される)
substr($url, strlen($base)) ?: '/notice';
// substr(false, strlen($base)); // false
// substr('', strlen($base)); // false
// substr($base, strlen($base)); // ""
// WordPressでパーマリンクを相対パスに変換したい場合
substr(get_permalink(), strlen(home_url()));