如何在不同的自定义帖子类型之间设置父子关系


14

我刚刚在帖子类型“短片”和帖子类型“卡通系列”之间建立了帖子/父级关系。

我使用以下代码在meta框中添加内容,以从另一种帖子类型分配父项:

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

该系列的网址是:

domain/cartoon-series/series-name

我希望该集的网址为:

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

我想念什么?是否可以使整个帖子类型成为其他帖子类型的子类型?因此,我什至可以获取剧集列表的网址为:

domain/cartoon-series/series-name/episodes

谢谢!马特


根据要求,以下是有关两种自定义帖子类型的代码:

$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提供的导出代码。

我没有任何其他代码可以链接这两个CPT。也许那就是我所缺少的。我刚刚在网上找到了将metabox放在页面上进行链接的代码。做这项工作还不够吗?看起来它设置了post_parent。

谢谢!马特


对不起,我错了。父子关系设置正确。元框未使用元字段(这是我第一次感到困惑),它使用parent_id查询var,不需要更多代码来设置关系。问题是WordPress无法识别生成的URL。我一直在试图找到一个使它起作用的重写规则,但是我没有成功。我正在研究一个解决方案。
cybmeta

经过一番调查,我认为您无法使其按您想要的方式工作。将帖子类型作为其他帖子类型的父级似乎是不可能的。好吧,可能是因为您的代码实际上已经设置了这种关系,但是看到子帖子在前端不起作用。我尝试过重写规则,并试图pre_get_posts更改查询而没有成功,但其中涉及到一些我还无法理解的复杂问题。就像让猫成为狗的父母一样。我建议仅使用一种分层的帖子类型,或使用meta字段设置realtionship 。
cybmeta

我认为一种按部就班的职位非常适合您的情况。
cybmeta

2
我真的在尝试不要对此复杂化。如果有更优雅的解决方案,我会全神贯注。我是WP的新手,到目前为止到目前为止还不错,但是这一点让我很沮丧。通常,我只是将卡通系列作为一个类别,然后将其分配给剧集。问题是,除了剧集以外,我还有其他嵌套数据要进入卡通系列。因此,似乎动画片系列也需要成为CPT。情况很复杂!:-D您能仅使用一种分层的帖子类型向我解释您的意思吗?
马塔顿

Answers:


9

终于,我找到了一个可行的解决方案。可以按照您的方式注册卡通系列,但是剧集自定义帖子类型不能重制(我认为WordPress希望如果post_parentwp_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删除所有子集时也要删除吗?在管理员编辑屏幕中添加过滤器,以按帖子上级过滤剧集?在管理员编辑屏幕中修改剧集标题以显示父系列名称?


感谢您查看这个!您发布的代码似乎正在从网址中删除卡通系列的名称。不要将%series_name%替换为该情节的名称,而应将%series_name%作为该情节的父项的名称。剧集名称将在此之后。由于某些原因,我无法选择“卡通系列”框来选择父级。这就是为什么我认为情节需要分层的原因。试图找出原因。
马塔顿

是的,必须对情节进行分级,以便填充“卡通系列”元框。
马塔顿

由于情节是分层的,因此我可以设置父项,因此URL变得更糟。按照您的建议,我在URL中两次获得了序列名称。因此,domain/episodes/series-name/episode-name与以前相比,我得到了domain/episodes/series-name/series-name/episode-name
Mattaton

如我所说,情节不能是分层的。我修改了元框代码,以使用非分层帖子类型填充。使用我发布的确切代码,我对其进行了测试,并且可以正常工作。如果您使用其他代码,我不知道出什么问题了。只需复制并粘贴答案中的代码并进行测试即可。您可能需要禁用CPT UI插件,或者至少要从插件中删除自定义帖子类型,因为它们已在代码中注册。
cybmeta

抱歉,我很快扫描了一下,以为那部分是相同的。没错,该页面现在确实已加载,并且网址看起来正确。
马塔顿


-1

您将需要为此编写自己的URL解析代码,因为wordpress需要根据url结构知道它试图从数据库检索的帖子的类型,而您的url结构对此没有任何提示。

使用wordpress的重写规则API并不是一件容易的事,但是没有什么可以阻止您绕过重写机制并自己解析url。像1.运行wordpress重载规则。如果找到内容,则显示该内容并退出。2。获取网址的第一部分,检查是否有与期望的帖子类型3相符的帖子。在正确的类型中。4.如果所有内容都匹配,则显示找到的最后一个帖子,否则显示404页

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.