これはメモです

それ以上でもそれ以下でもないのです

PHP URLをいい感じに分解する

WordPressで、月別アーカイブパーマリンクを下記のように書き換えたいケースに遭遇した。

// これを
https://example.com/2022/11/?post_type=cpt

// こう書き換えたい
https://example.com/cpt/date/2022/11/

「URLは'/'で区切られてるからそれでexplode()して、ごにょごにょすればいけるでしょ」と思っていたが、そう甘くはなかった。

<?php
var_dump(explode('/', 'https://example.com/2022/11/?post_type=cpt'));
array(6) {
  [0]=>
  string(6) "https:"
  [1]=>
  string(0) ""
  [2]=>
  string(11) "example.com"
  [3]=>
  string(4) "2022"
  [4]=>
  string(2) "11"
  [5]=>
  string(14) "?post_type=cpt"
}

感じた問題点としては、

  1. 'https://'のスラッシュもヒットして消えてしまう
  2. '2022/11/'の部分など不要な部分まで分解される
  3. クエリはそのまま残るので、必要な部分を取り出すのにもうひと手間必要

という感じで、全体的に少し冗長に感じた。

なにかいい方法がないかとググったところ、良さそうな関数を発見。

parse_url()を使う

www.php.net

前述のURLに適用すると、こんな感じ。

<?php
var_dump(parse_url('https://example.com/2022/11/?post_type=cpt'));
array(4) {
  ["scheme"]=>
  string(5) "https"
  ["host"]=>
  string(11) "example.com"
  ["path"]=>
  string(9) "/2022/11/"
  ["query"]=>
  string(13) "post_type=cpt"
}

問題点の2.しか解決していないのだけど、より意図が明確になると感じたのでこちらを使用した。

一連の操作は以下の通り。

<?php
$url = 'https://example.com/2022/11/?post_type=cpt';
$url_frags = parse_url($url);

$origin = $url_frags['scheme'] . '//' . $url_frags['host'];
$post_type = str_replace('post_type=', '', $url_frags['query']);
$new_url = $origin . '/' . $post_type . '/date' . $url_frags['path']; // "https//example.com/cpt/date/2022/11/"

注意点

php.netにも記載があるように、

  • URLデコードされない
  • 不正なURLでも受け入れる

ため、デコードやチェックは自前で行う必要がある。

WordPressではwp_parse_url()を使う

WordPressのフォーマッタを入れていると、 wp_parse_url()を使えと怒られる。

これは、PHPのバージョン間でparse_url()の戻り値の一貫性を保つためのものらしい。そのためWordPressでURLを分解したい場合はwp_parse_url()を使うのがベターのよう。

[参考]