※タイトルがわかりづらいという指摘をいただき修正しました
##「既存投稿を、特定のページ[[から]]開い場合のみデザインを変えたい」
というのが、やりたいこと。
つまり、投稿Singleでの閲覧に、複数のデザイン=テンプレートを持つということ。
例えば、以下のレパートリーを、記事の項目を設定することなく利用可能となる。
- TOP→記事(普通に表示)
- iFrameで呼び出された場合、特定のデザインにする
- 「注目の記事」的なページからのリンクは、キラキラ演出する
(一般的には必須ではない独自の)制約
-
Getパラメータは利用禁止
-
WP的なセキュリティホールとかは一旦気にしない。
-
すでに数百の記事があり、どれを使うかは誰かの気分次第
- いつどのデザインをいつ使うかはマークアップの人が自由に決められるようにする
- サーバサイドエンジニアは関与しない
- 記事投稿者も関与しない # 関与できない
- いつどのデザインをいつ使うかはマークアップの人が自由に決められるようにする
改修前の状態と課題
今からカスタム項目で何かを設定して回るのは現実ではないので、URLで解決を図りたいと考えた。
現状では、 カテゴリ="blog"、投稿ID="001" とした場合、
http://{domain}/blog/001.html で表示が可能。
通常のWP設定であれば、以下のやり方がエレガント
今回は、前述の制約:Getパラメータ禁止という制約でこの案は使えない。
解決
WPではデフォルトで、「存在しないカテゴリでアクセス」をした場合、投稿IDから逆引きして、redirectしてくれる。
- 例:/sonzaisinai/001.html ----> /blog/001.html
つまりnot foundにならない。
これに応用して、以下で実現してみた。
// テンプレート振り分け
function custom_template_include( $template ) {
if (is_single()) {
// ここはもっと効率良く書くべきだけどベタベタに書く。
// ここでPHP的にURLを取得するのがポイント。WPの関数使うと、redirect結果になっていたり加工がはいっていることがある
$parts = explode('/', $_SERVER['REQUEST_URI']);
if (count($parts > 2)) {
if ($parts[count($parts) - 2] == 'sonzaisinai') {
$new_template = locate_template(array('single-sonzaisinai.php'));
if ($new_template != '')
return $new_template;
}
}
}
return $template;
}
add_filter('template_include', 'custom_template_include', 99);
// 前述の自動リダイレクトを切る
remove_filter('template_redirect', 'redirect_canonical');
思いつけば、結果は簡単だった。
これで、全く同様の投稿内容をURL次第で、利用テンプレートの切り替えが可能となった。
-
/blog/001.html ・・・singleテンプレートで表示
-
/sonzaisinai/001.html・・・single-sonzaisinaiテンプレートで表示
あとは、SEO的なことが気になれば、canonicalを設定したりで、Google先生に伝えれば良い。
メモ
- 本当にこれで大丈夫かは検証中だけど、だいたい良さそう
- セキュリティリスクについては、最低限、ホワイトボックス的に縛ってあるので、問題ない気もしている
if ($parts[count($parts) - 2] == 'sonzaisinai') {
- サイトによっては、本対応以上にリダイレクトを切るデメリットのほうが大きくなる場合がある
remove_filter('template_redirect', 'redirect_canonical');