自定义帖子类型和分类法使用相同的 slug 和重写

Posted

技术标签:

【中文标题】自定义帖子类型和分类法使用相同的 slug 和重写【英文标题】:Custom Post type and Taxonomy using same slug with rewrite 【发布时间】:2018-09-23 06:20:37 【问题描述】:

这是我第一次尝试使用 WordPress 重写规则,所以请多多包涵。问题是我添加到我的投资组合中的所有项目都有多个类别。我想在显示投资组合帖子时从 url 中删除类别。

site.com/portfolio -> 有效

site.com/portfolio/category/ -> 有效

site.com/portfolio/category/post-added-to-portfolio/ -> 有效,但我不想这样做

site.com/portfolio/post-added-to-portfolio/ -> 不起作用,但应该这样做

/* Post Type: Portfolio */
$labels = array(
    "name" => __( "Portfolio", "" ),
    "singular_name" => __( "Portfolio", "" ),
);
$args = array(
    "label" => __( "Portfolio", "" ),
    "labels" => $labels,
    "description" => "",
    "public" => true,
    "publicly_queryable" => true,
    "show_ui" => true,
    "show_in_rest" => false,
    "rest_base" => "",
    "has_archive" => "portfolio",
    "show_in_menu" => true,
    "exclude_from_search" => false,
    "capability_type" => "post",
    "map_meta_cap" => true,
    "hierarchical" => true,
    "rewrite" => array( "slug" => "portfolio", "with_front" => true ),
    "query_var" => true,
    "supports" => array( "title", "editor" ),
    "taxonomies" => array( "services" ),
);
register_post_type( "portfolio", $args );   

/* Taxonomy: Services */
$labels = array(
    "name" => __( "Services", "" ),
    "singular_name" => __( "Service", "" ),
);
$args = array(
    "label" => __( "Services", "" ),
    "labels" => $labels,
    "public" => true,
    "hierarchical" => true,
    "label" => "Services",
    "show_ui" => true,
    "show_in_menu" => true,
    "show_in_nav_menus" => true,
    "query_var" => true,
    "rewrite" => array( 'slug' => 'portfolio', 'with_front' => true, ),
    "show_admin_column" => false,
    "show_in_rest" => false,
    "rest_base" => "",
    "show_in_quick_edit" => false,
);
register_taxonomy( "services", array( "portfolio" ), $args );

// handle redirects for taxonomy
add_action('generate_rewrite_rules', 'generate_taxonomy_rewrite_rules');
function generate_taxonomy_rewrite_rules( $wp_rewrite ) 
  $rules = array();
  $post_types = get_post_types( array( 'name' => 'portfolio', 'public' => true, '_builtin' => false ), 'objects' );
  $taxonomies = get_taxonomies( array( 'name' => 'services', 'public' => true, '_builtin' => false ), 'objects' );
  foreach ( $post_types as $post_type ) 
    $post_type_name = $post_type->name;
    $post_type_slug = $post_type->rewrite['slug'];
    foreach ( $taxonomies as $taxonomy ) 
      if ( $taxonomy->object_type[0] == $post_type_name ) 
        $terms = get_categories( array( 'type' => $post_type_name, 'taxonomy' => $taxonomy->name, 'hide_empty' => 0 ) );
        foreach ( $terms as $term ) 
          $rules[$post_type_slug . '/' . $term->slug . '/?$'] = 'index.php?' . $term->taxonomy . '=' . $term->slug;
          $rules[$post_type_slug . '/' . $term->slug . '/page/?([0-9]1,)/?$'] = 'index.php?' . $term->taxonomy . '=' . $term->slug . '&paged=' . $wp_rewrite->preg_index( 1 );
        
      
    
  
  $wp_rewrite->rules = $rules + $wp_rewrite->rules;

【问题讨论】:

我有您的问题的解决方案。我已经在我的一篇博文中解决了这个问题:[从所有 WordPress 帖子的永久链接中轻松删除“/Category”基础][1] [1]:siradhana.com/blog/… 只是想知道,为什么在注册分类法时,在 args 中,您拥有与注册 CPT 时相同的 slug 'portfolio'? 它删除了不必要的 url 结构。 如果您将永久链接结构设置为http://example.com/%postname%/,您将获得您想要的“投资组合”URL 结构;即 example.com/portfolio/sample-portfolio,其中 sample-portfolio 是“portfolio”块。这没有发生,还是您使用了不同的永久链接结构? 两次使用相同的 slug 不是一个好主意,而且几乎肯定会导致问题和意外行为。似乎这个问题的答案只是正确使用 WordPress 中的永久链接设置。您当前的永久链接结构是什么? 【参考方案1】:

经过一周的努力,我终于解决了这个问题。我将帖子类型保持原样。我将generate_rewrite_rules 函数替换为以下内容。

add_filter('request', 'setTermRequest', 1, 1 );
function setTermRequest($query)
    $tax_name = 'services';
    if( $query['attachment'] ) :
        $include_children = true;
        $name = $query['attachment'];
    else:
        $include_children = false;
        $name = $query['name'];
    endif;
    $term = get_term_by('slug', $name, $tax_name); // get the current term to make sure it exists
    if (isset($name) && $term && !is_wp_error($term)): // check it here
        if( $include_children ) 
            unset($query['attachment']);
            $parent = $term->parent;
            while( $parent ) 
                $parent_term = get_term( $parent, $tax_name);
                $name = $parent_term->slug . '/' . $name;
                $parent = $parent_term->parent;
            
         else  unset($query['name']); 
        switch( $tax_name ):
            case 'category':
                $query['category_name'] = $name; // for categories
                break;
            
            case 'post_tag':
                $query['tag'] = $name; // for post tags
                break;
            
            default:
                $query[$tax_name] = $name; // for another taxonomies
                break;
            
        endswitch;
    endif;
    return $query;

add_filter( 'term_link', 'writeTermPerm', 10, 3 );
function writeTermPerm( $url, $term, $taxonomy )
    $taxonomy_name = 'services';
    $taxonomy_slug = 'services';
    if ( strpos($url, $taxonomy_slug) === FALSE || $taxonomy != $taxonomy_name ) return $url;
    $url = str_replace('/'.$taxonomy_slug, '/portfolio', $url);
    return $url;

在修复 url 结构之后,我将以下代码添加到我的 taxonomy-services.php 文档中,以便在一个文件中控制整个系统。

locate_template( 'archive-portfolio.php', true );

【讨论】:

以上是关于自定义帖子类型和分类法使用相同的 slug 和重写的主要内容,如果未能解决你的问题,请参考以下文章

不同的重写动态 slug 被视为重复

拥有一个与自定义帖子类型“front”slug 标题相同的 WordPress 页面

自定义帖子类型 Slug 重写问题

自定义帖子类型 Slug 冲突

根据 Wordpress 中的自定义字段值批量重写帖子 slug

无法重命名自定义帖子类型的 slug