如何在Gutenberg编辑器中因重复slug存为草稿时显示错误提示
解决Gutenberg编辑器中重复Slug的错误提示问题
问题背景
我正在开发一个WordPress站点,需要防止创建slug重复的页面或文章。现有自定义插件可检测slug是否重复,当检测到重复(如尝试创建另一个slug为about的页面)时,文章会自动存为草稿,这部分功能正常。但Gutenberg编辑器中未显示错误提示,希望显示如下样式的提示:
<p class="text-danger">A post with this slug already exists. The post has been saved as a draft.</p>
让用户明白文章未发布或定时的原因。
解决方案
一、修改PHP插件代码
调整原插件的状态传递逻辑,适配Gutenberg的异步保存机制,并添加必要的REST支持:
<?php /* Plugin Name: Duplicate Slug Checker Description: Prevents WordPress from creating duplicate slugs like "about-2". Forces post to draft and alerts user. Version: 1.8 Author: Your Name */ if (!defined('ABSPATH')) exit; // 1. 检测重复Slug add_filter('wp_unique_post_slug', 'prevent_duplicate_slug_and_force_draft', 10, 6); function prevent_duplicate_slug_and_force_draft($slug, $post_ID, $post_status, $post_type, $post_parent, $original_slug) { global $wpdb; $existing = $wpdb->get_var($wpdb->prepare(" SELECT ID FROM $wpdb->posts WHERE post_name = %s AND post_type = %s AND ID != %d AND post_status != 'trash' LIMIT 1 ", $original_slug, $post_type, $post_ID)); if ($existing) { // 标记需要显示提示(针对当前用户和文章) update_user_meta(get_current_user_id(), 'duplicate_slug_alert_' . $post_ID, true); // 返回原slug避免生成about-2这类后缀 return $original_slug; } return $slug; } // 2. 强制设置为草稿 add_filter('wp_insert_post_data', function($data, $postarr) { $post_ID = isset($postarr['ID']) ? (int) $postarr['ID'] : 0; if (get_user_meta(get_current_user_id(), 'duplicate_slug_alert_' . $post_ID, true)) { $data['post_status'] = 'draft'; } return $data; }, 10, 2); // 3. 注册REST端点,供JS查询是否需要显示提示 add_action('rest_api_init', function() { register_rest_route('duplicate-slug/v1', '/alert/(?P<id>\d+)', [ 'methods' => 'GET', 'callback' => 'get_duplicate_slug_alert', 'permission_callback' => function($request) { $post_id = $request->get_param('id'); return current_user_can('edit_post', $post_id); } ]); }); function get_duplicate_slug_alert($request) { $post_id = $request->get_param('id'); $has_alert = get_user_meta(get_current_user_id(), 'duplicate_slug_alert_' . $post_id, true); // 读取后立即删除标记,避免重复显示 if ($has_alert) { delete_user_meta(get_current_user_id(), 'duplicate_slug_alert_' . $post_id); } return rest_ensure_response(['show_alert' => $has_alert]); } // 4. 加载编辑器脚本与样式 add_action('enqueue_block_editor_assets', function () { // 加载自定义JS wp_enqueue_script( 'check-duplicate-slug', plugin_dir_url(__FILE__) . 'js/check-slug.js', ['wp-dom-ready', 'wp-edit-post', 'wp-data', 'wp-api-fetch', 'wp-notices'], '1.1', true ); // 传递REST基础URL wp_add_inline_script('check-duplicate-slug', 'const DUPLICATE_SLUG_REST_URL = "' . esc_url(rest_url('duplicate-slug/v1/alert/')) . '";', 'before'); // 添加自定义样式 wp_add_inline_style('wp-edit-blocks', ' .duplicate-slug-alert { color: #dc3232; padding: 12px; background: #fef0f0; border-left: 4px solid #dc3232; margin: 16px 0; } '); });
二、替换JS代码(check-slug.js)
使用Gutenberg的原生通知组件显示提示,风格与编辑器UI统一:
document.addEventListener('DOMContentLoaded', async () => { // 获取当前编辑的文章ID const postId = wp.data.select('core/editor').getCurrentPostId(); if (!postId) return; // 查询是否需要显示重复Slug提示 const response = await wp.apiFetch({ path: DUPLICATE_SLUG_REST_URL + postId, method: 'GET' }); if (response.show_alert) { // 使用Gutenberg的通知系统添加错误提示 wp.data.dispatch('core/notices').createNotice( 'error', 'A post with this slug already exists. The post has been saved as a draft.', { isDismissible: true, className: 'duplicate-slug-alert' } ); } });
三、关键说明
- 替换原有的
transient为用户元数据,确保提示仅针对当前操作的用户和文章,避免多用户冲突。 - 使用Gutenberg内置的
wp-notices组件显示提示,完全贴合编辑器原生风格。 - 通过REST API查询提示状态,适配Gutenberg的异步保存流程,确保提示能准确触发。
- 自定义样式实现了与需求中
text-danger一致的视觉效果。
内容的提问来源于stack exchange,提问作者Ankaj Rana
相关产品推荐
相关产品推荐

