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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 01:44:54