WordPress链接配置冲突:CPT移除Slug与文章加blog前缀共存问题
解决CPT无slug与文章加blog前缀的冲突问题
1. 先调整ACF Pro里的CPT配置
在ACF创建Books/Movies这两个自定义文章类型时,找到「重写设置」:
- 「slug」还是填
books/movies(别删,内部规则要用来识别) - 取消勾选「使用前台前缀」(避免和blog前缀搅在一起)
- 「公开查询」必须设为true,不然前端查不到CPT内容
2. 修正生成无slug链接的钩子
替换你现在用的post_type_link代码,只针对目标CPT修改链接:
function remove_cpt_slug_from_permalink($post_link, $post) { // 只处理Books和Movies这两种CPT if (in_array($post->post_type, array('books', 'movies')) && $post->post_status === 'publish') { $post_link = str_replace('/' . $post->post_type . '/', '/', $post_link); } return $post_link; } add_filter('post_type_link', 'remove_cpt_slug_from_permalink', 10, 2);
3. 核心:让WordPress正确识别无slug的CPT请求
这步是解决404的关键,通过pre_get_posts钩子,让根路径的请求先检查是不是CPT内容,再查普通文章:
function parse_cpt_without_slug($query) { // 跳过后台、搜索、非主查询的情况 if (is_admin() || !$query->is_main_query() || $query->is_search()) { return; } // 当请求是单页且没指定post_type时,检查是否是CPT的内容 if ($query->is_single() && empty($query->query['post_type'])) { $post_name = $query->query['name']; // 查这个文章名是不是Books或Movies里的内容 $cpt_post = get_page_by_path($post_name, OBJECT, array('books', 'movies')); if ($cpt_post) { // 强制设置正确的post_type $query->set('post_type', $cpt_post->post_type); // 重置查询参数,确保能找到对应的CPT文章 unset($query->query['name']); $query->query['p'] = $cpt_post->ID; $query->query_vars['p'] = $cpt_post->ID; } } } add_action('pre_get_posts', 'parse_cpt_without_slug', 10);
4. 修复原带slug的CPT URL(可选)
如果需要兼容旧的mydomain.com/books/my-book1这类链接,加个重定向规则,让它跳转到无slug的新链接:
function redirect_old_cpt_slug_urls($request) { if (isset($request['post_type']) && in_array($request['post_type'], array('books', 'movies')) && isset($request['name'])) { $post = get_page_by_path($request['name'], OBJECT, $request['post_type']); if ($post) { wp_redirect(get_permalink($post), 301); exit; } } return $request; } add_filter('request', 'redirect_old_cpt_slug_urls');
5. 最后一定要刷新重写规则
进后台「设置」→「固定链接」,啥都不用改,直接点「保存更改」,让WordPress更新路由规则。
冲突原因说明
当你把固定链接设为/blog/%postname%/后,WordPress默认会把根路径的所有单页请求优先匹配普通文章(哪怕这个文章不存在),导致CPT的无slug请求被直接判定为不存在,返回404。上面的pre_get_posts钩子就是在查询前先检查有没有对应的CPT内容,把优先级调过来。
内容的提问来源于stack exchange,提问作者Nathan Bernard
相关产品推荐
相关产品推荐

