WordPress 5.4.1の仕様変更
WordPress 5.4.1で、permalinkの仕様が変更された。それに伴い、日時ベースのURLを採用していたfukumoto.orgも影響を受けている。
具体的には、以下のようなpermalinkを使用していると、個別ページではなくarchiveページが表示される仕様となった。
/%year%/%monthnum%/%day%/%hour%/%minute%/%second%/
理由がセキュリティ絡みだけに、この方針が覆ることはないだろう。対処方法はいくつかあるが、いずれも一長一短がある。
新しいpermalinkに更新する
日時ベースのURLをすっぱりと諦めて新しいpermalinkに移行するのが正攻法だ。post_idかpostnameを末尾に付ける方法が、既存のURLからの変更も少なく最も簡便だろう。後述する既存URLへのアクセスを受け付けて互換性を保つ方法とも親和性が高い。
fukumoto.orgでも末尾にpost_idを付加する方法をとることにした。postnameの方が望ましいのはわかるが、日本語のタイトルがURLに含まれるのはあまりに冗長だし、今から3,000件近くの記事すべてにslugを付けるのも現実的ではない。
とはいえ、新しいpermalinkに修正しただけでは、既存のURLへのアクセスに支障が生じる。今までの個別記事ページへアクセスしたらarchiveページになっていたというのはあまり望ましくない。これを解決するために、既存のURLへのアクセスも拾えるように工夫することにした。
parse_queryをhookする
既存のURLを活かす最も手軽な方法は、parse_queryをhookし日時ベースのURLが来た際に強制的にarchiveページではなくsingleページを表示するようにする実装だ。この方法は手軽でかつfunctions.phpで完結するので取り扱いが楽だ。具体的なコードは以下のようになる。
function _date_time_based_permalink( $wp_query ) {
$qv = $wp_query->query_vars;
if ( is_numeric($qv['year']) && is_numeric($qv['monthnum']) && is_numeric($qv['day']) && is_numeric($qv['hour']) && is_numeric($qv['minute']) && is_numeric($qv['second']) ) {
$wp_query->is_single = true;
$wp_query->is_archive = false;
}
}
add_action( 'parse_query', '_date_time_based_permalink' );
この方法で動作するのならば、permalinkを更新せずともよいのではないかと思われるかもしれないが、それでは以下のような問題が生じる。あくまでも、既存のURLとの互換性のためだけに残す程度にとどめておくのが良いと思う。
- 秒単位まで一致するような記事が発生しない小規模サイトでは問題とならないものの、そもそもの仕様変更に至ったセキュリティ上の問題が解決できていない
- 厳密には個別ページにアクセスしているわけではないため、一部のアクセス分析などが動作しなくなる
- 個別ページから編集に入れないため、過去の記事をメンテナンスする際に少々不便
コードに手を入れる
もう一つ最後の手段としてWordPressのコードに直接手を入れる方法もある。具体的には、/wp-includes/class-wp-query.php 内の parse_query() あたりをいじれば何とかなる。上で紹介したparse_queryをhookする方法で生じる問題点を回避できるのは魅力的だが、WordPressが更新されるたびに追随するのは一苦労だ。新たなセキュリティホールを生む可能性もあり、お勧めしない。fukumoto.orgでもこの方法は見送った。
コメント