WordPress/memo/is_404 関数が正しく動かない

そもそもの発端としては 404 画面を出したいのに、WordPress ではデフォルトで 404 画面が出ないという珍挙動することだった。 それを探っていくうちにこういうことに。

現象としてはこれと同様である

WordPress:力技で404リダイレクトする方法 - Qiita

この状態での現象の一例。全部発生しない場合もある。

WordPress がリンク切れを嫌うユーザのためにデフォルトでそれっぽい URL だったら類推して適当な画面を表示するというクソ機能を実装しているのだが、 その機能とパーマリンク設定が絶妙に変なことになるとこの現象が発生するっぽい

以下のような設定をやっているとなるこの現象になる可能性がある

それの対処法としては .htaccess に

ErrorDocument 404 /index.php?error=404

これを書く。当然駄目。

次にあるのが、この URL を修正する機能を切ってしまうというもの

function disable_redirect_canonical($redirect_url){
    if(is_404()){
        return false;
    }
    return $redirect_url;
}
add_filter('redirect_canonical', 'disable_redirect_canonical');

これも駄目。なぜなら、is_404 が true にならないからである。 そもそも今回の現象としてリダイレクトしていないのでそもそもこれ動いてない。

では結局どうすればいいかというと

である。こうすると内部的にスイッチが切り替わるらしく 404 が正常に判定されるようになる。 当然、redirect_canonical が動作するようになるので、そもそも動作しないように

function disable_redirect_canonical($redirect_url){
    return false;
}
add_filter('redirect_canonical', 'disable_redirect_canonical');

どんな状況でも完全オフにする。

内部を探っていくと、このパーマリンク設定というのは wp_options テーブルあたりの permalink_structure というキーに対して保存されるようだ。 中を見ると、画面上での「カスタム構造」とされている部分の内容がそのまま入っていて、これは設定値があるように見えているのは単なる UI の見せ方であって、 内容は、この形式で解釈するか否かしか無い。

ここでこの permalink_structure というキーをソースコード上で探っていくと、

./wp-includes/class-wp-rewrite.php

このあたりのみで使われていて、このファイルでは、パーマリンクを使うか使わないかみたいなスイッチがこのキーの内容があるか無いかによって判定されているのだ。 なので、このへんの値をちゃんと入れてやると、そっち系の処理に入ってくれるという仕掛けである。

基本の場合は URL はすべて index.php 経由の page_id 指定になるので、そもそも間違ったURLを補完するという対象すら無いということで、このロジックをパスするように書かれている。 パーマリンクのカスタム構造は自由度が高く、それぞれ専用に分岐して対処するという書き方はかなり難しいと思われる。なので内部のロジックは文字列っぽいURLの組み合わせに対して全般的に対処するようになっているのだろう。