お忙しい中質問を閲覧していただきありがとうございます。
現在独学でWordPressを学習中なのですが、その最中、リライトルールというとても複雑な問題にぶつかってしまいました…
詳しい方がいらっしゃいましたら是非ご助力いただけたらと思います。
前提・実現したいこと
--- 実現したいこと
各記事ページに詳細ページを設置したい。
例)
記事タイトル:サンプル1
記事スラッグ:sample1
パーマリンク:http://example.com/sample1/
詳細ページ :http://example.com/sample1/detail1/type1
上記を、
http://example.com/sample1/detail2/type1
http://example.com/sample3/detail3/type3
のように複数種類作ってみたいです。
最終的には、detail, type毎に使うテンプレートを変えて表示する予定です。
--- 前提
WordPress 4.7.8
PHP 7.0.18
使用テーマ SKT Design Agency
現状
functions.phpに以下を追記し、テスト用固定ページ(スラッグ名:rewriterules)を作成しリライトルールの追加が出来るか試してみました。
add_action('init', 'my_add_single_tag_permastruct');
function my_add_single_tag_permastruct() {
add_rewrite_tag("%detail%", '([^/]+)', "detail=");
add_rewrite_tag("%type%", '([^/]+)', "type=");
$single_struct = '/rewriterules/%detail%/%type%';
add_permastruct('mysingleperma', $single_struct, array("feed" => false));
}
この状態だと、http://example.com/rewriterules/detail1/type1/
にアクセスした際の404エラーは消えましたが、トップページが表示されている状態です。
下記はリライトルールに追加された内容です。
Rule | Rewrite | Source |
---|---|---|
rewriterules/([^/]+)/([^/]+)/page/?([0-9]{1,})/?$ | index.php?detail=$matches[1]&type=$matches[2]&paged=$matches[3] | mysingleperma |
rewriterules/([^/]+)/([^/]+)/?$ | index.php?detail=$matches[1]&type=$matches[2] | mysingleperma |
rewriterules/([^/]+)/page/?([0-9]{1,})/?$ | index.php?detail=$matches[1]&paged=$matches[2] | mysingleperma |
rewriterules/([^/]+)/?$ | index.php?detail=$matches[1] | mysingleperma |
ここからadd_rewrite_rule();を使用し、add_permastruct();で追加したルールを元にURLの書き換えを行うのだと思うのですが、そこのやり方に関しての参考サイトを上手く探すことが出来ませんでした…
また、現状で実装してみたものは固定ページのURLでしたが、これを記事ページでも行えるのでしょうか?
気になっている点は、add_permastruct();やadd_rewrite_rule();の中に記事のスラッグなどという可変的なモノを入れられるのか?ということです。
試したこと
finctions.php
add_action('init', 'my_add_single_rewrite_rules');
add_filter('query_vars', 'my_add_single_query_vars1');
add_filter('query_vars', 'my_add_single_query_vars2');
function my_add_single_rewrite_rules() {
add_rewrite_rule(
'rewriterules/?[^/]*/?[^/]*',
'index.php?pagename=rewriterules&detail=$matches[1]&type=$matches[2]',
'top'
);
}
function my_add_single_query_vars1($vars) {
$vars[] = 'detail';
return $vars;
}
function my_add_single_query_vars2($vars) {
$vars[] = 'type';
return $vars;
}
この場合、http://example.com/rewriterules/detail1/type1/
にアクセスするとhttp://example.com/rewriterules/
と同じページが表示されましたが、固定ページ名の部分を記事スラッグに変えられないのではないかと思い、現状の方法に変えました。
追記
--- 一応意図通り動いたコード
functions.php
add_action('init', 'my_add_single_rewrite_endpoint');
function my_add_single_rewrite_endpoint() {
add_rewrite_endpoint('detail01', EP_PERMALINK, 'type');
add_rewrite_endpoint('detail02', EP_PERMALINK, 'type');
add_rewrite_endpoint('detail03', EP_PERMALINK, 'type');
}
これで記事ページのパーマリンクの最後に/detail01/xxx/
を付けてアクセスすると無事アクセスでき、最後のxxxの部分の文字列がtypeという名前のパラメータとして認識されるようになりました。
しかし、テンプレートに切り替えは、
<?php
$url = $_SERVER['REQUEST_URI'];
if (strstr($url, 'detail01')) {
get_template_part('single-detail01');
}elseif (strstr($url, 'detail02')) {
get_template_part('single-detail02');
}elseif (strstr($url, 'detail03')) {
get_template_part('single-detail03');
}else {
get_template_part('single-top');
}
というゴリ押し分岐で実装しています…笑
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+3
複雑なリライトルールを追加するときは
書き換え後のURLを直接叩いてみて
表示されることを確認した後で
リライトルール追加をする方が
間違っている箇所を探しやすくて吉
閑話休題
そこまでやったらそのURLにアクセスした際に
グローバル変数$wp_queryの
$wp_query->query_vars['detail']と
$wp_query->query_vars['type']に
それぞれ値が入っている状態になっているはずです
これを使ってtemplate_includeでテンプレートを切り替えたりします
add_filter('template_include', function($tmp){
global $wp_query;
if(
isset($wp_query->query_vars['detail']) and
isset($wp_query->query_vars['type']
)){
return get_theme_file_path(
'page-'.$wp_query->query_vars['detail'].'-'.
$wp_query->query_vars['type'].'.php'
);
}
return $tmp;
});
リライトルール追加時に気をつけなくてはいけないのは
ルールが引っ掛ける範囲が広すぎて
他のページを表示できなくなってしまうことがあるということです
なので([^/]+)で表されるような部品をリライトルールに使う際には
それ以外の部分に一意な文字列を含むのが望ましいです
リライトルールのパターンが
([^/]+)/([^/]+)/([^/]+)/
みたいなものになるとかなり多くのURLパターンを引っ掛けてしまい
意図しないリライトがされてしまう可能性が高くなります
記事ページのスラッグをリライトルールに使いたい場合は
([^/]+)/detail/([^/]+)/
などのような置き換えルールになるようにした方がより安全でしょう
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.10%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2017/12/25 10:28
数日間PCに触れずにいたので反応が遅れてしまいました…
回答の内容を今すぐ試したいのですが、実は質問を投稿した後、少し違う実装方法で記事ページに対してのリライトルール追加に成功しました。(正確には、一応自分の意図していた動作をするようになりました。)
これが果たして安全な方法なのかが分からないので、是非一度コードを拝見していただきたいです。
質問に追記しますので、お時間がありましたら回答の程よろしくお願い致します。
2017/12/25 11:18
というのでページの判定を行うのは不確実です
例えばこの先、各詳細ページについての説明をする固定ページを作るってことになって
about-detail01なんて名前で作っちゃったらこれも引っかかっちゃいます
しかもこういうことするのはこんな基本部分の仕様についてなんて
すっかり忘れた頃だったりするのでタチが悪いです
変な禁忌事項を作ってしまうような仕様は避けましょう
URLの文字列を検索する今のやり方を通すとしても、少なくとも
if(isset($wp_query->query_vars['type']))ぐらいの判定はした方がいいでしょう
細かいことですが「特定の文字列が含まれているか」は
strposでやったほうが軽いです
2017/12/25 11:29
私もパーマリンクに同一文字列が含まれていた場合の対処法をどうしようかと考えていましたが、この方法で行うなら二重チェックは必須だと思います。
何度も回答頂きありがとうございます!
この後回答にある方法も試してみて、しっくり来る方を実装したいと思います!