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

Laravel中如何验证带CKEditor样式的商品描述唯一性?

解决Laravel中CKEditor描述内容的唯一性验证问题

这个场景太常见了!CKEditor输出的是带HTML标签的内容,而Laravel默认的unique规则只会死板匹配数据库里的原始HTML——哪怕两个描述的文字完全一样,只要标签样式不同(比如一个是<p>红富士苹果</p>,另一个是<p style="color:#f00">红富士苹果</p>),就会被判定为不同内容,自然起不到重复验证的作用。

下面给你两种可行的解决方案,按需选择:

方案一:自定义验证闭包(快速实现,无需改表)

不需要额外修改数据库,直接在验证逻辑里先把HTML内容清理成纯文本,再去数据库匹配核心内容的唯一性:

public function rules() {
    return [
        'description' => [
            'required',
            'min:5',
            'max:255',
            // 自定义唯一性验证逻辑
            function ($attribute, $value, $fail) {
                // 第一步:把输入的HTML清理成标准化纯文本
                $cleanedInput = trim(preg_replace('/\s+/', ' ', strip_tags($value)));
                
                // 第二步:在数据库里用相同规则清理字段,匹配内容
                $query = \App\Models\Product::whereRaw(
                    "trim(regexp_replace(strip_tags(description), '\\\\s+', ' ')) = ?",
                    [$cleanedInput]
                );
                
                // 如果是编辑商品,要排除当前商品本身,避免误判
                if ($currentProduct = $this->route('product')) {
                    $query->where('id', '!=', $currentProduct->id);
                }
                
                // 查到重复就抛出错误提示
                if ($query->exists()) {
                    $fail('该商品描述的核心内容已存在,请修改后重试。');
                }
            },
        ],
    ];
}

这里的关键是PHP端和数据库端用完全一致的清理规则:先去掉HTML标签,再把所有连续空白(换行、空格、制表符)换成单个空格,最后去掉首尾空格,确保哪怕空白格式不同,只要文字内容一致就会被识别为重复。

方案二:新增纯文本字段(性能更优,适合大数据量)

如果你的商品数据量比较大,方案一中的whereRaw加函数的查询会无法利用数据库索引,性能会打折扣。这时候可以新增一个字段专门存储清理后的纯文本描述:

  1. 生成迁移文件添加字段:
php artisan make:migration add_description_clean_to_products_table --table=products
  1. 编辑迁移文件:
public function up() {
    Schema::table('products', function (Blueprint $table) {
        $table->string('description_clean', 255)->after('description')->nullable();
    });
    
    // 批量更新已有商品的纯文本字段(可选,处理历史数据)
    \App\Models\Product::query()->update([
        'description_clean' => DB::raw("trim(regexp_replace(strip_tags(description), '\\\\s+', ' '))")
    ]);
}

public function down() {
    Schema::table('products', function (Blueprint $table) {
        $table->dropColumn('description_clean');
    });
}
  1. 运行迁移:
php artisan migrate
  1. 在Product模型中自动同步纯文本字段:
protected static function boot() {
    parent::boot();
    
    // 保存/更新商品时,自动生成对应的纯文本描述
    static::saving(function ($product) {
        $product->description_clean = trim(preg_replace('/\s+/', ' ', strip_tags($product->description)));
    });
}
  1. 修改验证规则,直接验证纯文本字段的唯一性:
public function rules() {
    $rules = [
        'description' => 'required|min:5|max:255',
        'description_clean' => 'unique:products',
    ];
    
    // 编辑商品时,排除当前商品的ID
    if ($currentProduct = $this->route('product')) {
        $rules['description_clean'] .= ",id,$currentProduct->id";
    }
    
    return $rules;
}

这种方案的优势是description_clean可以添加数据库索引,查询效率会高很多,而且验证逻辑更简洁。

小提醒:方案一中的regexp_replace是MySQL 8.0+支持的,如果是旧版本MySQL,可以用多次replace来处理空白字符,或者调整清理规则适配你的数据库版本。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:09:22