【PHP】絶対URLから相対URLへの変換/相対パスの取得【WordPress】

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の抽出

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()));
広告