带有自定义链接的嵌套自定义帖子类型


9

我试图建立一个具有永久链接的多级自定义帖子类型结构authors/books/chapters,其作者,书籍和章节均设置为自己的自定义帖子类型。例如,此网站上的典型URL可能看起来像example.com/authors/stephen-king/the-shining/chapter-3/

每章只能属于一本书,每本书只能属于一位作者。我考虑过使用分类法代替作者和书籍的CPT,但是我需要将元数据与每个项目相关联,为此我更喜欢发布界面。

在大多数情况下,我都会通过简单地将每个自定义帖子设置为CPT上一级条目的子级来实现。例如,我创建“第3章”,并使用自定义元框将“发光”指定为父对象。“ The Shining”又将“ Stephen King”作为父母。建立这些关系我没有任何麻烦。

我在CPT子弹中使用了重写标签,并且永久链接想要工作,但它们不太正确。使用重写分析器,我可以看到重写规则实际上是生成的,但是它们似乎顺序不正确,因此其他规则将首先处理。

这是我的重写分析器的屏幕截图。

这是我注册我的CPT的方式:

function cpt_init() {

  $labels = array(
    'name' => 'Authors'
   );

  $args = array(
    'labels' => $labels,
    'public' => true,
    'publicly_queryable' => true,
    'show_ui' => true, 
    'show_in_menu' => true, 
    'query_var' => true,
    'rewrite' => array(
        'slug' => 'author',
        'with_front' => FALSE,
    ),
    'with_front' => false,
    'capability_type' => 'post',
    'has_archive' => false, 
    'hierarchical' => true,
    'menu_position' => null,
    'supports' => array( 'title', 'editor' )
  ); 

  register_post_type('authors',$args);

  $labels = array(
    'name' => 'Books'
  );

  $args = array(
    'labels' => $labels,
    'public' => true,
    'publicly_queryable' => true,
    'show_ui' => true, 
    'show_in_menu' => true, 
    'query_var' => true,
    'rewrite' => array(
        'slug' => 'author/%authors%',
        'with_front' => FALSE,
    ),
    'with_front' => false,
    'capability_type' => 'post',
    'has_archive' => false, 
    'hierarchical' => true,
    'menu_position' => null,
    'supports' => array( 'title', 'editor' )
  ); 

  register_post_type('books',$args);


  $labels = array(
    'name' => 'Chapters'
   );

  $args = array(
    'labels' => $labels,
    'public' => true,
    'publicly_queryable' => true,
    'show_ui' => true, 
    'show_in_menu' => true, 
    'query_var' => true,
    'rewrite' => array(
        'slug' => 'author/%authors%/%books%',
        'with_front' => FALSE,
    ),
    'with_front' => FALSE,
    'capability_type' => 'post',
    'has_archive' => false, 
    'hierarchical' => true,
    'menu_position' => null,
    'supports' => array( 'title', 'editor' )
  ); 

  register_post_type('chapters',$args);

}

add_action( 'init', 'cpt_init' );

那么,有什么方法可以改变我的重写规则的优先级,从而使作者,书籍和章节都首先匹配?

我也知道我将不得不添加一个post_type_link过滤器,但这似乎首先使固定链接正确。如果有人知道我在哪里可以找到该过滤器工作原理的全面概述,将不胜感激。


您是否考虑过仅使用Pages?您将自动获得正确的永久链接结构。
迈克尔·汉普顿

我绝对考虑过。页面的问题是单个作者可能拥有100个孙子项,这在页面管理中将很难管理。另外,我们需要能够按帖子类型进行查询。
道尔顿

我正在研究一个解决方案,但我有一个快速的问题:在每个永久链接的前面都有“作者”是关键吗?因为那似乎是顽固派。我认为这使WordPress有点混乱,尤其是因为这是一个永久链接,也用于WP作者页面。如果需要“作者”,我认为整个事情还是可行的……只会更加复杂。
雷切尔·卡登

糟糕,我没有意识到作者会与内置的WP作者产生冲突。不,这不是必需的,可以是任何东西。我以为是CPT,所以我在那里需要一些东西,但它可能也很容易成为“作家”或其他任何东西。
道尔顿

我意识到,混淆实际上是由于CPT共享“作者”作为基础。一旦将“作者”设置为CPT“作者”的子弹,然后将CPT“书籍”设置为“ author /%author%”,将CPT“章节”设置为“ author /%author%/%book%” ”,然后WordPress认为“书籍”的帖子和“章节”的帖子实际上是“作者”的分层子帖子。那有意义吗?在我的测试中,您可以将“作者”作为CPT“作者”的基础,并且效果很好。因此,将我之前的问题替换为:您是否需要“作者”,或者该子弹可以以%author%开头?
雷切尔·卡登

Answers:


11

如果你想保持“作家”作为永久链接基蛞蝓,即example.com/authors/stephen-king/的“作家” CPT,example.com/authors/stephen-king/the-shining/为“书籍” CPT和example.com/authors/stephen-king/the-shining/chapter-3/对于“章节” CPT,WordPress会认为几乎所有内容都是“作者”帖子或“作者”的分层子级之后,由于事实并非如此,WordPress最终变得非常混乱。

话虽如此,这里有一个非常基本的解决方法,但前提是您的永久链接结构始终遵循相同的顺序,即“作者”一词后面始终是作者子词,该子词后面始终是书子词,该子词后总是一章子弹,那么你应该很好。

在此解决方案中,无需在自定义帖子类型定义中为“章节”和“书本”定义重写段,而是将“作者”重写段设置为简单的“作者”,将以下代码放入您的functions.php中文件并“刷新”您的重写规则。

add_action( 'init', 'my_website_add_rewrite_tag' );
function my_website_add_rewrite_tag() {
    // defines the rewrite structure for 'chapters', needs to go first because the structure is longer
    // says that if the URL matches this rule, then it should display the 'chapters' post whose post name matches the last slug set
    add_rewrite_rule( '^authors/([^/]*)/([^/]*)/([^/]*)/?','index.php?chapters=$matches[3]','top' );
    // defines the rewrite structure for 'books'
    // says that if the URL matches this rule, then it should display the 'books' post whose post name matches the last slug set
    add_rewrite_rule( '^authors/([^/]*)/([^/]*)/?','index.php?books=$matches[2]','top' );   
}

// this filter runs whenever WordPress requests a post permalink, i.e. get_permalink(), etc.
// we will return our custom permalink for 'books' and 'chapters'. 'authors' is already good to go since we defined its rewrite slug in the CPT definition.
add_filter( 'post_type_link', 'my_website_filter_post_type_link', 1, 4 );
function my_website_filter_post_type_link( $post_link, $post, $leavename, $sample ) {
    switch( $post->post_type ) {

        case 'books':

            // I spoke with Dalton and he is using the CPT-onomies plugin to relate his custom post types so for this example, we are retrieving CPT-onomy information. this code can obviously be tweaked with whatever it takes to retrieve the desired information.
            // we need to find the author the book belongs to. using array_shift() makes sure only one author is allowed
            if ( $author = array_shift( wp_get_object_terms( $post->ID, 'authors' ) ) ) {
                if ( isset( $author->slug ) ) {
                    // create the new permalink
                    $post_link = home_url( user_trailingslashit( 'authors/' . $author->slug . '/' . $post->post_name ) );
                }
            }

            break;

        case 'chapters':

            // I spoke with Dalton and he is using the CPT-onomies plugin to relate his custom post types so for this example, we are retrieving CPT-onomy information. this code can obviously be tweaked with whatever it takes to retrieve the desired information.
            // we need to find the book it belongs to. using array_shift() makes sure only one book is allowed
            if ( $book = array_shift( wp_get_object_terms( $post->ID, 'books' ) ) ) {

                // now to find the author the book belongs to. using array_shift() makes sure only one author is allowed
                $author = array_shift( wp_get_object_terms( $book->term_id, 'authors' ) );

                if ( isset( $book->slug ) && $author && isset( $author->slug ) ) {
                    // create the new permalink
                    $post_link = home_url( user_trailingslashit( 'authors/' . $author->slug . '/' . $book->slug . '/' . $post->post_name ) );
                }

            }

            break;

    }
    return $post_link;
}

了解有关CPT-onomies插件的更多信息


效果很好,谢谢!我觉得我学到了很多东西。CPT-onomies插件也非常酷。wordpress.org/extend/plugins/cpt-onomies
Dalton

我觉得随着“图书馆”的发展,您可能会遇到一些障碍,但是我已经有了一些代码,因此,如果您愿意,请告诉我。
雷切尔·卡登

@RachelCarden如果两本书标题相同但作者不同,您该怎么办?重写的URL中将发生冲突!您如何解决呢?
Segfault

1
@Segfault您将必须检索所有作者子代码,以便可以将它们硬编码到重写规则中:foreach($ author_slugs as $ author_slug){add_rewrite_rule('^ authors /'。$ author_slug。'/([ ^ /] *)/([[^ /] *)/?','index.php?authors ='。$ author_slug。'&chapters = $ matches [2]','top'); add_rewrite_rule('^ authors /'。$ author_slug。'/([^/]*)/?','index.php?authors='。$ author_slug。'&books = $ matches [1]','top') ; }
Rachel Carden

@Segfault 如果使用的是CPT-onomy,则可以使用get_terms(),也可以使用get_posts()来检索帖子名称/内容。
雷切尔·卡登

4

我在这种情况下没有亲身经验,但是Randy Hoyt上周末在WordCamp San Fran上做了一个有关“从属帖子类型”的演讲,听起来像您在说什么。

这是他的演讲页面,其中包括他的演示幻灯片和指向他为使用从属帖子类型而构建的插件的链接:http : //randyhoyt.com/wordpress/subordinate-post-types/


谢谢,这看起来是不错的资源。尚不清楚这是否支持孙辈关系(在我的测试中似乎不支持),并且它实际上对永久链接没有帮助。我已经想出了一种建立孩子/父母关系的方法(尽管这是一种很好的方法),但是永久链接确实是我现在停留的问题。
道尔顿

1

规则将按照添加额外永久结构的顺序添加到WP_Rewrite的extra_rules_top中。因此,切换注册帖子类型的顺序将切换生成重写规则的顺序,从而使章节重写首先匹配。但是,由于您正在使用其他post_types中的query_var,因此wp_query可能最终在匹配所需的章节之前将其中之一作为查询的帖子名称进行匹配。

我将创建新的重写标签来表示父作者和父书的占位符,即:

add_rewrite_tag('%parent-book%', '([^/]+)', 'parent_book=');

这样做时,您必须过滤“ query_vars”以使“ parent_book”公开。然后,您需要在pre_get_posts中添加一个过滤器,以将设置为parent_book query_var的名称转换为post_id并将其设置为“ post_parent”。


您能否提供您提到的过滤器的代码示例?另外,孙代CPT的重写标签会是什么样?
道尔顿
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.