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


16

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

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

だから私が望んでいるのは、文字通りコア「ページ」とまったく同じ動作ですが、カスタム投稿タイプです。期待どおりに投稿タイプを登録しましたが、管理者では完全に機能します。各ニュースレター「投稿」に親と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 */

また、階層関係が作成された標準のコア「ページ」もあり、管理画面ではまったく同じように見えますが、実際にはフロントエンドでも機能します(親URLと子URLの両方が正常に機能します)。

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

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 ),

私のカスタム投稿タイプの子供と通常のページの子供の唯一の目に見える違いは、私の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を含むさまざまなテーマでこれを試しましたが、それは単に私の一部に欠けているテンプレートがないことを確認するためです。

Rewrite Rules Inspectorを使用すると、次のような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

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

デフォルトでは、階層型CPTは説明したとおりに動作します。固有のスラッグ接頭辞、この場合の「ニュースレター」は、さまざまな投稿タイプへのリクエストを区別する方法を書き換えエンジンに知らせることです。

これらのCPT登録引数は正常に見えますが、CPTが要求された場合、pagenameクエリ変数には値がなく、nameクエリ変数はnewsletterここと同じである必要があります。したがって、セットアップのどこかに競合があるようです。

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

  1. リストを見ながら、ニュースレターCPTのすべてのルールをページ書き換えルールのにリストする必要があります。「ソース」列をスキャンして、これが正しいことを確認します。
  2. それがチェックアウトしたら、「最初の記事」CPTのURLをURLに一致」フィールドに入力し、「フィルター」ボタンをクリックして、一致するルールを確認します。ニュースレタールールとページルールに一致する必要がありますが、ニュースレタールールが最初になります。

問題が明らかにならない場合は、post_namewp_postsを検索して、「first-article」スラッグを含む他の投稿を見つけ、衝突があるかどうかを確認します。念のため、「ニュースレター」も検索してください。

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

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番目のステップでリクエストが間違ったルールに一致した場合は特に、各ステップの後に書き換えルールをフラッシュします(「パーマリンク」画面を別のタブで開いたままにして更新します)。


これらのコメントでは十分な書式設定ができないため、書き換えルールインスペクターからの出力を表示するように質問を編集しました。CPTのルールは、リストの一番上、他の何よりも前に表示されます-しかし、以下のルールのどれが「ページ」ルールであるかは明確ではありません(明確ではありません)。また、post_name列に衝突はありません。
身体の

適切なパーマリンク構造につ​​いて何か考えはありますか?書き直しインスペクターでさらに混乱させるように思われる/%postname%/ので、私は戻ってきました/%category%/。私は/%category%/、CPTが「親」を意味するように魔法のようにマップされていると主張する人を見たことがありますが、これは真実ではありません。
体細胞

その出力は別のプラグイン用であるように見えるため、ルールの「ソース」が表示されません。どちらにしても、ルールはうまく一致しているように見えます。回答を編集してスニペットを追加し、リクエストの早い段階でクエリ変数を検査して、それらが正しく設定されていることを確認しました。
ブレイディVercher

パーマリンク構造につ​​いては、このカテゴリを含めることは好きではありません。役に立たない別の可動部分であり、投稿は複数のカテゴリに属する​​ことができます。将来パーマリンク構造を変更したり、スラッグプレフィックスなしで別のCPTをロードしたりする可能性がある場合は、のような固定されたユニークなもので構造を「名前空間化」することをお勧めします/blog/%postname%/
ブレイディVercher

これは正しいプラグインですが、「書き換えアナライザー」と「書き換えルール」の2つのページがあり、どちらもテストURLを提供します。他のページを試してみましたが、最初のインデントされたグループのソースは「プログラム」、2番目のグループは「ページ」として表示されていました。
身体の

5

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%/と、ニュースレター/親/子が正常に機能します。


上記の私のコードはそれを示していませんでしたが、私はpage-attributesサポートにあります(これは実際に親子関係を割り当てるためのメタボックスを表示するだけで、パーマリンクには影響しません)-404を取得します。どのパーマリンク構造を設定する必要がありますか?またはそれは重要ですか?
身体の

@somatic私はそれをもう一度テストしましたが、パーマリンクについてはそれが問題になるかどうかはわかりませんが、私は答えを更新しました。
Bainternet

'labels'の引数配列を追加すると(adminにCPTが表示されないため)、この基本的な例はtwentlytwelveを使用したWP3.5の標準インストールで動作することを確認できます。しかし、私はあなたのregister_post_type$ argsのいくつかの重要な違いに気づいています:私は使用しました'rewrite' => array( 'slug' => 'newsletter', 'with_front' => false )、あなたはちょうど使用しましたtrue。また、単にに合格truehas_archive、そこで私はスラッグを渡しました。しかし、私があなたの引数にマッチしたとき、私はまだ404を得ました...まだ私が間違っているところを追跡しようとしています。
身体の

3

オフにしてからもう一度オンにしてみましたか?」など)?

その場合:すべてのプラグインを無効にしてTwentyElevenに切り替えた後でも、これは発生しますか? ここに画像の説明を入力してください

さらにデバッグするには、GitHubに移動してToschos "Rewrite" Pluginを取得します。次に、wp.orgの公式プラグインリポジトリに切り替えて、MonkeyManRewriteAnalyzer Pluginを取得します。両方を少し接着するための拡張機能を作成しました。これにより、セットアップに関する多くの詳細がわかります。


まあ、すべてを無効にすると、この質問のポイントであるカスタム投稿タイプはありません...しかし、はい、私は20のテーマでも試しました。私が見ることができるものから、パーマリンク自体が整形式であるように、私はまだいくつかの必要なプラグを掘り下げて、クエリをマングルしているものを確認しています。
体細胞

@somatic もちろんあなたを無効にしない :)
kaiser

@somaticアップデートを参照してください。
カイザー

1

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

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

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

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

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

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

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


オブジェクトget_queried_object()をインターセプトせずにラッパー関数を使用することもでき$wpdbます。
カイザー

しかし、それ$queryはどれをつかみますか?私はのためにフィルタ内にこれを使用していparse_queryて、特に特定の照会オブジェクトを取得する必要$query...フィルタから渡される
体細胞

のフィルター内でラッパーを使用してみましたparse_query。同じ404エラーが再び発生しました。私は何を複製するいくつかの方法を見つけるために持っているget_queried_object()...これらのフィルタを汚損することなく、ありませんが
体細胞

-2

WPの最新バージョンを実行していますか?これは最初の質問だと思います(テクニカルサポートに電話して、コンピューターが接続されているかどうかを尋ねるときなど)。この問題は最新のバージョンアップデートで対処されたと読んだためです。

この問題に対処するdigwp.comの投稿があります(http://digwp.com/2011/06/dont-use-postname/)。どうやらWPは投稿とページの違いを簡単に判断できず、URLをテキストベースのオプションで開始すると、WPはフラグをトリガーして、所有するすべてのページ/投稿のルールを作成します。サイトに多くのコンテンツがある場合、膨大な数のリクエストが発生する可能性があり、サーバーがタイムアウトする可能性があります。これにより、ページがあっても404が大量に発生します。

そう。最初に数値ベースの構造を使用し、次にテキストベースの構造を使用する場合、404の問題が解決されることを期待しています。さて、SEOの問題を考慮して、日付構造は使用しませんが、その決定はあなたにとって十分に論理的です。


2
私は3.5です。WP3.3.1現在、digiwpのこの問題は修正されています。
身体の
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.