You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让多个WordPress自定义文章类型共享同一根slug?

问题描述
  • 当前URL格式:
    • www.domain.com/villas/single-villa
    • www.domain.com/yachts/single-yacht
    • www.domain.com/cars/single-car
  • 期望URL格式:
    • www.domain.com/listing/single-villa
    • www.domain.com/listing/single-yacht
    • www.domain.com/listing/single-car

尝试修改CPT注册代码中的slug参数,但仅最后一个注册的CPT生效,其余均返回404错误。以下是其中一个CPT的注册代码(已翻译中文):

function wtp_yachts() {

    $labels = array(
        'name'                  => _x( '游艇', 'Post Type General Name', 'text_domain' ),
        'singular_name'         => _x( '游艇', 'Post Type Singular Name', 'text_domain' ),
        'menu_name'             => __( '游艇', 'text_domain' ),
        'name_admin_bar'        => __( '编辑游艇', 'text_domain' ),
        'archives'              => __( '归档', 'text_domain' ),
        'parent_item_colon'     => __( '父游艇:', 'text_domain' ),
        'all_items'             => __( '所有游艇', 'text_domain' ),
        'add_new_item'          => __( '添加新游艇', 'text_domain' ),
        'add_new'               => __( '添加新游艇', 'text_domain' ),
        'new_item'              => __( '新游艇', 'text_domain' ),
        'edit_item'             => __( '编辑游艇', 'text_domain' ),
        'update_item'           => __( '更新游艇', 'text_domain' ),
        'view_item'             => __( '查看游艇', 'text_domain' ),
        'search_items'          => __( '搜索', 'text_domain' ),
        'not_found'             => __( '未找到', 'text_domain' ),
        'not_found_in_trash'    => __( '回收站中未找到', 'text_domain' ),
        'featured_image'        => __( '特色图片', 'text_domain' ),
        'set_featured_image'    => __( '设置特色图片', 'text_domain' ),
        'remove_featured_image' => __( '移除特色图片', 'text_domain' ),
        'use_featured_image'    => __( '用作特色图片', 'text_domain' ),
        'insert_into_item'      => __( '插入到项目中', 'text_domain' ),
        'uploaded_to_this_item' => __( '上传到此项目', 'text_domain' ),
        'items_list'            => __( '卡片列表', 'text_domain' ),
        'items_list_navigation' => __( '项目列表导航', 'text_domain' ),
        'filter_items_list'     => __( '筛选项目列表', 'text_domain' ),
    );
    $args = array(
        'label'                 => __( '游艇', 'text_domain' ),
        'description'           => __( '游艇', 'text_domain' ),
        'labels'                => $labels,
        'supports'              => array( 'title', 'thumbnail', 'editor'),
        'hierarchical'          => false,
        'public'                => true,
        'show_ui'               => true,
        'show_in_menu'          => true,
        'menu_position'         => 5,
        'menu_icon'             => 'dashicons-palmtree',
        'show_in_admin_bar'     => true,
        'show_in_nav_menus'     => true,
        'can_export'            => true,
        'has_archive'           => true,
        'exclude_from_search'   => false,
        'publicly_queryable'    => true,
        'capability_type'       => 'page',
        'show_in_rest' => true,
        'rewrite'      => array(
            'slug'       => '', 
            'with_front' => false, 
        ),
    );
    register_post_type( 'yachts', $args );

}
add_action( 'init', 'wtp_yachts', 0 );
解决方案

问题根源

多个CPT共用同一个根slug时,WordPress的重写规则会被最后注册的CPT覆盖,导致前面的CPT无法匹配到正确规则,返回404。

具体步骤

  1. 修改所有CPT的注册参数
    将每个CPT的rewrite参数改为以下配置,同时关闭归档页避免冲突:

    'rewrite' => array(
        'slug' => 'listing',
        'with_front' => false,
        'feeds' => false, // 禁用feed避免冲突
        'pages' => false  // 禁用分页避免冲突
    ),
    'has_archive' => false // 关闭归档页,避免根slug下的归档冲突
    
  2. 添加自定义重写规则
    在主题的functions.php中添加以下代码,为每个CPT单独注册重写规则:

    function custom_listing_rewrite_rules() {
        // 替换为你所有的CPT名称
        $post_types = array('villas', 'yachts', 'cars');
        foreach ($post_types as $type) {
            add_rewrite_rule(
                '^listing/([^/]+)/?$',
                'index.php?post_type=' . $type . '&name=$matches[1]',
                'top'
            );
        }
    }
    add_action('init', 'custom_listing_rewrite_rules', 10);
    
  3. 修正请求解析逻辑
    添加parse_request钩子,让WordPress能根据文章名称匹配到对应CPT:

    function custom_listing_parse_request($query) {
        if (!is_admin() && $query->is_main_query() && isset($query->query['name'])) {
            $post_name = $query->query['name'];
            // 替换为你所有的CPT名称
            $post = get_page_by_path($post_name, OBJECT, array('villas', 'yachts', 'cars'));
            if ($post) {
                $query->set('post_type', $post->post_type);
            }
        }
        return $query;
    }
    add_action('parse_request', 'custom_listing_parse_request');
    
  4. 刷新重写规则
    登录WordPress后台,进入「设置」→「固定链接」,无需修改任何设置,直接点击「保存更改」,触发重写规则刷新。

注意事项

  • 若你的CPT有自定义分类或其他附加规则,需额外调整重写规则避免冲突。
  • 这种共用根slug的做法确实不符合WordPress最佳实践,后续维护可能遇到兼容性问题,建议仅在迫不得已时使用。

内容的提问来源于stack exchange,提问作者mar Ko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 00:54:52