web-dev-qa-db-ja.com

階層的なカスタム投稿タイプのパーマリンクをページのように機能させる

私はここでカスタム投稿タイプのパーマリンクについてのあらゆる質問を掘り下げましたが、ほとんどはカスタム分類法の書き換えに関する問題、または明らかにflush_rewrite_rules()の欠落のいずれかと思われます。しかし、私の場合は、メタボックスなどの属性を適切に「サポート」して、階層型に設定した(したがって、親子関係を割り当てることができる)カスタム投稿タイプ(分類法なし)のみを使用しています。書き換えルールを1000の異なる方法でフラッシュしました。私はさまざまなパーマリンク構造を試しました。しかし、子URLは常に404になります。

私はもともと(p2pを使って) "parent"と "child"要素のための独立したカスタム投稿タイプを持っていました、そしておそらく "parental"グルーピングの分類法を使っても問題ないでしょう。しかし、クライアントにとっては、ページのように「記事」が管理者に表示されるときに階層を視覚化するのが最も簡単です。子が親の下に表示され、先頭に「 - 」が付いたシンプルなツリーです。正しい順序ドラッグアンドドロップで順序を割り当てるためのさまざまな方法も使用できます。分類法(またはp2p)でグループ化すると、管理者リストに「投稿」のフラットリストが表示されますが、これは視覚的には明らかではありません。

だから私がやっているのは文字通りコアの "pages"と全く同じ振る舞いですが、私のカスタム投稿タイプです。私は期待通りに投稿タイプを登録しました、そして管理者でそれは完全に働きます - 私はそれぞれのニュースレター "post"に親とmenu_orderを割り当てることができます、それらは編集リストに正しく現れます:

Spring 2012
— First Article
— Second Article

そして彼らのパーマリンク出現は適切に構築されるべきです。実際、構造について何かを変更したり、投稿タイプを登録するときに書き換えスラグを変更したりしても、自動的に正しく更新されるので、問題はありません。

http://mysite.com/parent-page/child-page/                  /* works for pages! */
http://mysite.com/post-type/parent-post/child-post/        /* should work? */
http://mysite.com/newsletter/spring-2012/                  /* works! */
http://mysite.com/newsletter/spring-2012/first-article/    /* 404 */
http://mysite.com/newsletter/spring-2012/second-article/   /* 404 */

私はまた階層的な関係が作成された標準的なコア「ページ」を持っており、それらは管理者では全く同じように見えますが、実際にはフロントエンドでも動作します。

私のパーマリンク構造は次のように設定されています。

http://mysite.com/%postname%/

私もこれを試みました(私の場合は意味がありませんでしたが、他にも多くの回答が必要であることを示しているようでした)。

http://mysite.com/%category%/%postname%/

私の登録CPT引数は次のとおりです。

$args = array(
    'public'                => true,
    'publicly_queryable'    => true,
    'show_ui'               => true,
    'has_archive'           => 'newsletter',
    'hierarchical'          => true,
    'query_var'             => true,
    'supports'              => array( 'title', 'editor', 'thumbnail', 'page-attributes' ),
    'rewrite'               => array( 'slug' => 'newsletter', 'with_front' => false ),

私のカスタム投稿タイプchildrenと通常のpage childrenの唯一の目に見える違いは、私のCPTがパーマリンク構造の最初にスラッグを持ち、その後に親/子スラッグが続くということです。 (ページが単に親/子スラッグで始まっているところ、「接頭辞」はありません)。なぜこれが問題を引き起こすのか、私にはわかりません。これはまさにそのような階層型CPTパーマリンクがどのように振る舞うべきかを示す記事がたくさんあるようです - しかし、私のものはうまく形成されてはいますが機能しません。

その404ページのquery_varsを調べると、私を困惑させるのも私の子ページを「見つける」ためのWPの正しい値が含まれているようですが、うまくいかないことです。

$wp_query object WP_Query {46}
public query_vars -> array (58)
'page' => integer 0
'newsletter' => string(25) "spring-2012/first-article"
'post_type' => string(10) "newsletter"
'name' => string(13) "first-article"
'error' => string(0) ""
'm' => integer 0
'p' => integer 0
'post_parent' => string(0) ""
'subpost' => string(0) ""
'subpost_id' => string(0) ""
'attachment' => string(0) ""
'attachment_id' => integer 0
'static' => string(0) ""
'pagename' => string(13) "first-article"
'page_id' => integer 0
[...]

私は、これが私の側に欠けているテンプレートではないことを確実にするために、12を含むさまざまなテーマでこれを試しました。

書き換えルールインスペクタを使用して、これはurlに現れるものです: http://mysite.com/newsletter/spring-2012/first-article/

newsletter/(.+?)(/[0-9]+)?/?$   
       newsletter: spring-2012/first-article
           page: 
(.?.+?)(/[0-9]+)?/?$    
       pagename: newsletter/spring-2012/first-article
           page: 

他のインスペクタページにどのように表示されるか

RULE:
newsletter/(.+?)(/[0-9]+)?/?$
REWRITE:
index.php?newsletter=$matches[1]&page=$matches[2]
SOURCE:
newsletter

この書き換えの出力は、私に次のような「かわいらしくない」パーマリンクがうまくいくと信じるように導きました。

http://mysite.com/?newsletter=spring-2012&page=first-article

404ではありませんが、子ではなく、親CPT項目「ニュースレター」が表示されます。リクエストは次のようになります。

Array
(
    [page] => first-article
    [newsletter] => spring-2012
    [post_type] => newsletter
    [name] => spring-2012
)
15
somatic

したがって、完全にクリーンなインストールと単一のCPT宣言で期待される階層ページの動作を得ることができることを確認した後、CPT作成の処理に使用する自分のプラグイン内のどこかに障害があることがわかりました(非常に複雑、カスタムメタボックス、分類法を処理します)など)。問題は、リライトまたはクエリの問題をチェックするためのすべてのアドバイスにも関わらず、明らかに間違っているものを見つけることができなかったことです。すべてのフィルターとフックをチェックし、各ポイントでクエリを表示し、404の原因となるものは何も表示しませんでした。

そのため、9つの大きなクラスのそれぞれを手動で無効化/有効化してから、それらのうち少なくとも2つが404の原因であることがわかり、各機能を1つずつ通過して無効化/有効化してから、行をトレースするタスクを残しましたそれらの関数内の行-たとえ理由がわからなくても、404の原因を正確に確認しようとする総当たり攻撃。

$query->get_queried_object()を使用すると結果が生じることがわかりました。このラッパー関数を使用すると、実際に$ query自体が変更されるように見えます。クエリを変更する2つのクラスにまたがる3つのフィルターが関係しました:parse_queryposts_orderbyposts_join-渡された$query argですべてのコールバック関数が$query->get_queried_object()を呼び出して、いくつかの条件付きテストを実行し、クエリ変数を時々変更しました特別なソート順の場合)。不思議なことに、これらの関数は、実際に機能するように設計されたものでうまく機能しました。にもかかわらず関数の使用。以前に返された$ queryの問題に気づいたことはありません!

どういうわけか、数十のライブプロダクションサイトで1年以上開発と使用を行った後、この間違いによる悪影響を経験したことはありませんでした。階層的なCPTに挑戦したときだけ、この小さな違いが突然物事を壊しました。これは私がこれで私を非常に苦労させたものの一部です-私が知ることができるように、私のクエリフィルターは信頼できました!

この関数を呼び出すと、CPT子ページのこの小さな側面だけが壊れる理由がまだわからないことを告白しますが、他の問題が発生したことはありません。しかし、フィルターコールバック内で使用すると、返された$queryが何らかの形で破損することは明らかでした。この呼び出しを削除すると、404エラーが消えました。

すべてのヒントをありがとう-最終的な解決策が多少無関係であったとしても、私はそれぞれの答えから洞察を得たので、報奨金を分割できることを願っています。これは、長い間信頼性の高い方法で動作しているか、明らかなエラーが発生していない場合でも、コードを盲目的に信頼しないという教訓です。

時には、カイザーのチャートが非常にきちんと体現されているので、ライトが再び点灯するまでスイッチを投げ始める必要があります。私の場合、問題を確認する前に、同じトラブルシューティング戦略を関数の個々の行に至るまで実行する必要がありました。

1
somatic

今回はStack Exchangeに参加するのは今回が初めてですが、ここで試してみて、正しい方向に向けることができるかどうかを確認します。

デフォルトでは、階層CPTは今まで説明したとおりに動作します。ユニークなスラッグプレフィックス、この場合は "ニュースレター"は、書き換えエンジンに、異なる投稿タイプのリクエストを区別する方法を知らせることです。

これらのCPT登録引数は問題ないように見えますが、CPTが要求されたときはpagenameクエリ変数は値を持つべきではなく、ここでnameクエリ変数はnewsletterと同じになるはずです。

デバッグを容易にするには、 Rewrite Rules Inspector Plugin をインストールしてアクティブにしてから、画面の " ツール - > Rewrite Rules "にアクセスします。

  1. リストを見ている間、ニュースレターCPTのためのあなたのすべての規則はリストされているはずですすべての前にページ書き換え規則。 " Source "列をスキャンしてこれが正しいことを確認します。
  2. それがチェックアウトされている場合は、 " Match URL "フィールドに "first-article" CPTのURLを入力し、[Filter]ボタンをクリックしてどのルールが一致するかを確認します。ニュースレターのルールとページのルールに一致する必要がありますが、ニュースレターのルールが最初になります。

それでも問題が解決しない場合は、post_namewp_posts列を検索して、 "first-article"スラッグの付いた他の投稿を検索し、衝突があるかどうかを確認してください。念のために、 "newsletter"も検索してください。

次のスニペットを追加して、リクエストの早い段階でクエリ変数を調べて、書き換えルールの一致によって設定されているものを確認します(フロントエンドの子CPTにアクセスします)。 pagename変数がここに表示されない場合は、リクエストの後半で設定されています。

add_filter( 'request', 'se77513_display_query_vars', 1 );

function se77513_display_query_vars( $query_vars ) {
    echo '<pre>' . print_r( $query_vars, true ) . '</pre>';

    return $query_vars;
}

クエリ変数を変更するプラグインや関数が衝突を引き起こす可能性があるので、それでも問題がある場合は無効にします。また、特に上記の2番目のステップでリクエストが間違ったルールと一致した場合は、各ステップの後に書き換えルールをフラッシュします([パーマリンク]画面を別のタブで開いたまま更新します)。

14
Brady Vercher

parent/Childパーマリンクは、設定する限りすぐに使用できます

'hierarchical'=> true,
'supports' => array('page-attributes' ....

更新:

私はちょうどそれをもう一度テストしましたが、このテストケースで期待どおりに動作します:

add_action('init','test_post_type_wpa77513');
function test_post_type_wpa77513(){
    $args = array(
        'public' => true,
        'publicly_queryable' => true,
        'show_ui' => true, 
        'show_in_menu' => true, 
        'query_var' => true,
        'rewrite' => true,
        'capability_type' => 'post',
        'has_archive' => true, 
        'hierarchical' => true,
        'supports' => array( 'title', 'editor', 'thumbnail', 'page-attributes' )
    ); 

    register_post_type( 'newsletter', $args );
}

パーマリンクを/%postname%/に設定すると、ニュースレター/親/子が正常に機能します。

5
Bainternet

"電源を入れなおしてみましたか?" と尋ねる以外に、「プラグインはアクティブになっていますか。テーマはパーマリンクに対して何かをしていますか。 :分類の登録、投稿タイプ、書き換え規則の追加など)

もしそうなら:あなたがすべてのプラグインを無効にしてTwentyElevenに切り替えた後も、これは起こりますか? enter image description here

さらにデバッグするには、GitHubに進んで Toschos "Rewrite" Plugin _を取得してください。それから公式のプラグインレポジトリ wp.orgにあり、MonkeyManRewriteAnalyzerプラグインを理解する に切り替えてください。私は両方を少し一緒に接着するために少しの拡張さえ書きました。これはあなたのセットアップに関する多くの詳細をあなたに与えるでしょう。

3
kaiser