WordPress后台CPT自定义菜单:隐藏默认子菜单与保留分类法过滤问题
WordPress自定义文章类型后台菜单最优实现方案
1. 隐藏父菜单自动生成的同名子菜单
你之前使用javascript:void()作为父菜单slug的方式会导致默认子菜单与父菜单slug完全一致,remove_submenu_page无法正常匹配识别,替换为标准实现方案即可解决:
- 父菜单正常设置唯一的自定义slug,不使用js地址
- 父菜单回调函数配置为直接重定向到第一个子菜单,实现点击无跳转效果
- 注册完子菜单后直接调用
remove_submenu_page删除默认生成的同名子项
代码示例:
add_action('admin_menu', 'registro_digital_register_menu'); function registro_digital_register_menu() { // 注册父菜单 add_menu_page( __( 'Registro digital', 'peslam_cecr' ), __( 'Registro digital', 'peslam_cecr' ), 'administrator', 'registro-digital', // 自定义唯一slug 'registro_digital_redirect_first_submenu', // 重定向回调 'dashicons-media-document', 1 ); // 注册两个子菜单 add_submenu_page( 'registro-digital', __( 'Entradas', 'peslam_cecr' ), __( 'Entradas', 'peslam_cecr' ), 'administrator', 'edit.php?post_type=registro_digital&tipo_registro=entrada' ); add_submenu_page( 'registro-digital', __( 'Salidas', 'peslam_cecr' ), __( 'Salidas', 'peslam_cecr' ), 'administrator', 'edit.php?post_type=registro_digital&tipo_registro=salida' ); // 直接移除默认生成的同名子菜单 remove_submenu_page( 'registro-digital', 'registro-digital' ); } // 父菜单点击重定向到第一个子菜单 function registro_digital_redirect_first_submenu() { wp_redirect( admin_url( 'edit.php?post_type=registro_digital&tipo_registro=entrada' ) ); exit; }
2. 优化列表页搜索/筛选参数丢失问题
你之前基于referer判断跳转的方案兼容性差,referer容易丢失或被篡改,使用「查询逻辑修改+表单隐藏字段注入」的方案更稳定:
第一步:查询阶段自动注入分类过滤条件
不需要跳转,直接在主查询阶段按当前页面参数加上分类过滤:
add_action('pre_get_posts', 'filter_registro_digital_by_tipo'); function filter_registro_digital_by_tipo($query) { if (!is_admin() || !$query->is_main_query()) { return; } global $pagenow, $typenow; if ($pagenow == 'edit.php' && $typenow == 'registro_digital') { $tipo = isset($_GET['tipo_registro']) ? sanitize_text_field($_GET['tipo_registro']) : ''; if (in_array($tipo, ['entrada', 'salida'])) { $query->set('tax_query', [ [ 'taxonomy' => 'tipo_registro', 'field' => 'slug', 'terms' => $tipo ] ]); } } }
第二步:给列表页操作表单注入隐藏参数
在搜索、筛选表单中自动插入分类参数,提交时自动携带,不需要额外处理:
add_action('admin_footer-edit.php', 'add_tipo_registro_hidden_field'); function add_tipo_registro_hidden_field() { global $typenow; if ($typenow != 'registro_digital') { return; } $tipo = isset($_GET['tipo_registro']) ? sanitize_text_field($_GET['tipo_registro']) : ''; if (in_array($tipo, ['entrada', 'salida'])) { echo '<input type="hidden" name="tipo_registro" value="'.esc_attr($tipo).'">'; } }
额外优化:子菜单高亮匹配
访问对应分类列表页时自动高亮正确的子菜单:
add_filter('parent_file', 'fix_registro_digital_menu_highlight'); function fix_registro_digital_menu_highlight($parent_file) { global $pagenow, $typenow, $submenu_file; if ($pagenow == 'edit.php' && $typenow == 'registro_digital') { $tipo = isset($_GET['tipo_registro']) ? sanitize_text_field($_GET['tipo_registro']) : ''; $parent_file = 'registro-digital'; if ($tipo == 'entrada') { $submenu_file = 'edit.php?post_type=registro_digital&tipo_registro=entrada'; } elseif ($tipo == 'salida') { $submenu_file = 'edit.php?post_type=registro_digital&tipo_registro=salida'; } } return $parent_file; }
内容的提问来源于stack exchange,提问作者Carlos Crespo Moreno
相关产品推荐
相关产品推荐

