異なるカスタム投稿タイプ間の親子関係を設定する方法


14

投稿タイプ「エピソード」と投稿タイプ「漫画シリーズ」の間に投稿/親関係を設定しました。

このコードを使用してメタボックスに追加し、別の投稿タイプから親を割り当てます。

add_action('admin_menu', function() {
    remove_meta_box('pageparentdiv', 'episodes', 'normal');
});
add_action('add_meta_boxes', function() {
    add_meta_box('episodes-parent', 'Cartoon Series', 'episodes_attributes_meta_box', 'episodes', 'side', 'default');
});

function episodes_attributes_meta_box($post) {
    $post_type_object = get_post_type_object($post->post_type);
    if ( $post_type_object->hierarchical ) {
        $pages = wp_dropdown_pages(array('post_type' => 'cartoon-series', 'selected' => $post->post_parent, 'name' => 'parent_id', 'show_option_none' => __('(no parent)'), 'sort_column'=> 'menu_order, post_title', 'echo' => 0));
        if ( ! empty($pages) ) {
            echo $pages;
        } // end empty pages check
    } // end hierarchical check.
}

管理画面では、シリーズをエピソードの親として設定できましたが、投稿を表示しようとすると404が表示されます。URL構造は次のとおりです。

domain/episodes/series-name/episode-name

シリーズのURLは次のとおりです。

domain/cartoon-series/series-name

エピソードのURLは次のとおりです。

domain/cartoon-series/series-name/episode-name

私は何が欠けていますか?投稿タイプ全体を別の投稿タイプの子にすることは可能ですか?したがって、エピソードリストのURLを取得することもできます。

domain/cartoon-series/series-name/episodes

ありがとう!マット


要求されたとおり、問題の2つのカスタム投稿タイプのコードは次のとおりです。

$labels = array(
    "name" => "Cartoon Series",
    "singular_name" => "Cartoon Series",
    "menu_name" => "Cartoon Series",
    "all_items" => "All Cartoon Series",
    "add_new" => "Add New",
    "add_new_item" => "Add New Cartoon Series",
    "edit" => "Edit",
    "edit_item" => "Edit Cartoon Series",
    "new_item" => "New Cartoon Series",
    "view" => "View",
    "view_item" => "View Cartoon Series",
    "search_items" => "Search Cartoon Series",
    "not_found" => "No Cartoon Series Found",
    "not_found_in_trash" => "No Cartoon Series Found in Trash",
    "parent" => "Parent Cartoon Series",
    );

$args = array(
    "labels" => $labels,
    "description" => "",
    "public" => true,
    "show_ui" => true,
    "has_archive" => true,
    "show_in_menu" => true,
    "exclude_from_search" => false,
    "capability_type" => "post",
    "map_meta_cap" => true,
    "hierarchical" => true,
    "rewrite" => array( "slug" => "cartoon-series", "with_front" => true ),
    "query_var" => true,
    "supports" => array( "title", "revisions", "thumbnail" ),           );
register_post_type( "cartoon-series", $args );

$labels = array(
    "name" => "Episodes",
    "singular_name" => "Episode",
    );

$args = array(
    "labels" => $labels,
    "description" => "",
    "public" => true,
    "show_ui" => true,
    "has_archive" => true,
    "show_in_menu" => true,
    "exclude_from_search" => false,
    "capability_type" => "post",
    "map_meta_cap" => true,
    "hierarchical" => true,
    "rewrite" => array( "slug" => "episodes", "with_front" => true ),
    "query_var" => true,
    "supports" => array( "title", "revisions", "thumbnail" ),           );
register_post_type( "episodes", $args );

CPT UIプラグインを使用しているため、そのコードを直接編集することはできません。これは、CPT UIが提供するエクスポートコードです。

2つのCPTをリンクする他のコードはありません。たぶんそれは私が見逃していることです。リンクを行うためにページにメタボックスを配置するコードをオンラインで見つけました。仕事をするだけでは不十分ですか?post_parentを設定しているようです。

ありがとう!マット


申し訳ありませんが、私は間違っていました。親子関係が正しく設定されています。メタボックスはメタフィールドを使用していません(最初は混乱していました)。parent_idクエリ変数を使用し、関係を設定するためにコーディングする必要はありません。問題は、生成されたURLがWordPressで認識されないことです。私はそれを機能させる書き換えルールを見つけようとしましたが、成功しませんでした。現在、解決策を調査しています。
サイブメタ

いくつかの調査の後、私はあなたが望むように動作させることができないと思います。投稿タイプを他の投稿タイプの親として持つことは不可能のようです。あなたのコードでは、実際に関係が設定されている可能性がありますが、フロントエンドでは子の投稿を見ることができません。私はルールを書き直してpre_get_posts、クエリを変更するためにフックを試みましたが成功しませんでしたが、理解できないほど複雑なものが含まれています。猫が犬の親になるように。私は1つの階層的な投稿タイプのみを使用するか、メタフィールドを使用して現実設定することを提案します
サイブメタ

1つの階層型の投稿タイプがあなたの状況に完全に適合すると思います。
サイブメタ

2
私は本当にこれで複雑にならないようにしています。よりエレガントなソリューションが利用可能な場合、私はすべて耳です。私は一般にWPを初めて使用し、これまでのところかなりうまくやっていますが、これは私を困惑させました。通常、漫画シリーズをカテゴリにして、エピソードに割り当てるだけです。問題は、エピソード以外のネストされたデータが漫画シリーズの下にあることです。したがって、漫画シリーズもCPTである必要があるようです。それは複雑です!:-D階層的な投稿タイプを1つだけ使用することの意味を説明できますか?
マッタトン

回答:


9

最後に、実用的なソリューションを見つけました。漫画シリーズはあなたがしたように登録できますが、エピソードのカスタム投稿タイプは階層化できません(データベーステーブルpost_parentで関係が設定されている場合、WordPressは親コンテンツが子コンテンツと同じタイプであることを期待すると思いwp_postsます)。

エピソードを登録するとき、書き換えルールは必要なスラッグ、つまりに設定する必要がありますcartoon-series/%series_name%。次に、エピソードリンクをフィルター処理して%series_name%、親cartoon-series投稿タイプの実際の名前と、漫画シリーズの投稿タイプが要求されたときとエピソードであるときにWordPressに伝える書き換えルールで置き換えることができます。

add_action('init', function(){
    $labels = array(
        "name" => "Cartoon Series",
        "singular_name" => "Cartoon Series",
        "menu_name" => "Cartoon Series",
        "all_items" => "All Cartoon Series",
        "add_new" => "Add New",
        "add_new_item" => "Add New Cartoon Series",
        "edit" => "Edit",
        "edit_item" => "Edit Cartoon Series",
        "new_item" => "New Cartoon Series",
        "view" => "View",
        "view_item" => "View Cartoon Series",
        "search_items" => "Search Cartoon Series",
        "not_found" => "No Cartoon Series Found",
        "not_found_in_trash" => "No Cartoon Series Found in Trash",
        "parent" => "Parent Cartoon Series",
    );

    $args = array(
        "labels" => $labels,
         "description" => "",
        "public" => true,
        "show_ui" => true,
        "has_archive" => true,
        "show_in_menu" => true,
        "exclude_from_search" => false,
        "capability_type" => "post",
        "map_meta_cap" => true,
        "hierarchical" => true,
        "rewrite" => array( "slug" => "cartoon-series", "with_front" => true ),
        "query_var" => true,
        "supports" => array( "title", "revisions", "thumbnail" )
    );

    register_post_type( "cartoon-series", $args );

    $labels = array(
        "name" => "Episodes",
        "singular_name" => "Episode",
    );

    $args = array(
        "labels" => $labels,
        "description" => "",
        "public" => true,
        "show_ui" => true,
        "has_archive" => true,
        "show_in_menu" => true,
        "exclude_from_search" => false,
        "capability_type" => "post",
        "map_meta_cap" => true,
        "hierarchical" => false,
        "rewrite" => array( "slug" => "cartoon-series/%series_name%", "with_front" => true ),
        "query_var" => true,
        "supports" => array( "title", "revisions", "thumbnail" )
    );

    register_post_type( "episodes", $args );

});

add_action('add_meta_boxes', function() {
    add_meta_box('episodes-parent', 'Cartoon Series', 'episodes_attributes_meta_box', 'episodes', 'side', 'default');
});

function episodes_attributes_meta_box($post) {
        $pages = wp_dropdown_pages(array('post_type' => 'cartoon-series', 'selected' => $post->post_parent, 'name' => 'parent_id', 'show_option_none' => __('(no parent)'), 'sort_column'=> 'menu_order, post_title', 'echo' => 0));
        if ( ! empty($pages) ) {
            echo $pages;
        } // end empty pages check
}

add_action( 'init', function() {

    add_rewrite_rule( '^cartoon-series/(.*)/([^/]+)/?$','index.php?episodes=$matches[2]','top' );

});

add_filter( 'post_type_link', function( $link, $post ) {
    if ( 'episodes' == get_post_type( $post ) ) {
        //Lets go to get the parent cartoon-series name
        if( $post->post_parent ) {
            $parent = get_post( $post->post_parent );
            if( !empty($parent->post_name) ) {
                return str_replace( '%series_name%', $parent->post_name, $link );
            }
        } else {
            //This seems to not work. It is intented to build pretty permalinks
            //when episodes has not parent, but it seems that it would need
            //additional rewrite rules
            //return str_replace( '/%series_name%', '', $link );
        }

    }
    return $link;
}, 10, 2 );

:上記のコードを保存してから試す前に、書き換えルールをフラッシュすることを忘れないでください。に移動しwp-admin/options-permalink.phpて[保存]をクリックし、書き換えルールを再有効化します。

注2:おそらく、ページ編集の投稿で機能するために、より多くの書き換えルールを追加する必要があります。また、完全なソリューションを得るために、さらに作業が必要になる場合があります。たとえば、cartoon-seriesすべての子エピソードを削除するときに削除する場合などです。管理者編集画面にフィルターを追加して、投稿の親でエピソードをフィルターしますか?管理者編集画面でエピソードのタイトルを変更して、親シリーズ名を表示しますか?


これを見てくれてありがとう!投稿したコードは、漫画シリーズの名前をURLから削除しているようです。%series_name%をエピソードの名前に置き換える代わりに、%series_name%をエピソードの親の名前にする必要があります。エピソード名はその後になります。何らかの理由で、親を選択するために[漫画シリーズ]ボックスが表示されません。だから、エピソードは階層的である必要があると思いました。理由を理解しようとしています。
マッタトン

はい。カートゥーンシリーズのメタボックスにデータを入力するには、エピソードを階層化する必要があります。
マッタトン

エピソードが階層化されているため、親を設定できますが、URLが悪化しました。提案されたスラッグを使用して、URLでシリーズ名を2回取得します。だから、domain/episodes/series-name/episode-name以前のようにではなく、私はdomain/episodes/series-name/series-name/episode-name
マッタトン

私が言ったように、エピソードは階層的であってはなりません。メタボックスコードを変更して、非階層的な投稿タイプを入力しました。私が投稿した正確なコードを使用し、テストし、動作しています。別のコードを使用すると、何が間違っているのかわかりません。回答からコードをコピーして貼り付け、テストするだけです。CPT UIプラグインを無効にするか、少なくともコードに登録されているカスタム投稿タイプをプラグインから削除する必要がある場合があります。
サイブメタ

ああ、すみません、すぐにスキャンして、その部分は同じだと思いました。あなたは正しい、ページは今ロードされ、URLは正しく見える。
マッタトン


-1

wordpressはurl構造に基づいてDBから取得しようとする投稿のタイプを知る必要があるため、独自のURL解析コードを記述する必要があります。また、url構造はこれを示唆しません。

これは、wordpressの書き換えルールAPIを使用して行うのは非常に簡単なことではありませんが、書き換えメカニズムをバイパスして自分でURLを解析することを妨げるものはありません。1.のようなものは、wordpressのrewiteルールを実行します。コンテンツが見つかった場合は表示し、2を終了します。URLの最初の部分を取得し、予想される投稿タイプ3のスラッグに一致する投稿があるかどうかを確認します。正しいタイプ。4.すべてが一致する場合、最後に見つかった投稿が表示され、そうでない場合は404ページが表示されます

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.