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" }
感じた問題点としては、
- 'https://'のスラッシュもヒットして消えてしまう
- '2022/11/'の部分など不要な部分まで分解される
- クエリはそのまま残るので、必要な部分を取り出すのにもうひと手間必要
という感じで、全体的に少し冗長に感じた。
なにかいい方法がないかとググったところ、良さそうな関数を発見。
parse_url()
を使う
前述の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()
を使うのがベターのよう。
[参考]