Laravel怎么实现模型软删除与唯一联合索引_Laraveldeleted_at参与约束【方法】

小浩姑娘_5235

小浩姑娘_5235

2026-05-04

483人浏览

原创

软删除字段 deleted_at 默认参与唯一索引约束,因其存储具体时间而非 null,需通过数据库函数索引(mysql 8.0+)或部分索引(postgresql)实现仅对未删除记录生效的唯一性校验。

laravel怎么实现模型软删除与唯一联合索引_laraveldeleted_at参与约束【方法】

软删除字段 deleted_at 默认不参与唯一索引约束

这是最常被误解的一点:Laravel 的软删除只是给模型加了个 deleted_at 时间戳,并不会自动让数据库忽略已软删记录的唯一性检查。比如你建了 UNIQUE KEY `user_email_unique` (`email`),那即使某条记录 deleted_at 不为 NULL,再插入同邮箱的新记录仍会报 SQLSTATE[23000]: Integrity constraint violation。

根本原因在于——MySQL/PostgreSQL 的唯一索引默认对所有行生效,NULL 值在唯一索引中是允许重复的,但 Laravel 软删除写入的是具体时间(如 "2024-05-12 10:30:00"),不是 NULL,所以它会被当作普通非空值参与校验。

  • 软删除后 deleted_at 是 datetime 类型的具体时间,不是 NULL
  • 唯一索引不区分“逻辑删除”和“物理存在”,只看字段值是否重复
  • 想让它“不参与”,得靠数据库层面改造,不是靠 Laravel 模型配置

用函数索引(MySQL 8.0+)或部分索引(PostgreSQL)绕过已删除记录

核心思路是:把唯一性约束从「整列」变成「仅对未删除记录生效」。不同数据库实现方式不同,但目标一致——让已软删的行不进入索引范围。

MySQL 8.0+ 可用函数索引:

CREATE UNIQUE INDEX user_email_active_unique ON users (email) WHERE deleted_at IS NULL;

PostgreSQL 可用部分索引:

CREATE UNIQUE INDEX user_email_active_unique ON users (email) WHERE deleted_at IS NULL;

注意这两条语句长得像,但 MySQL 的 WHERE 是函数索引语法糖,PostgreSQL 的才是原生部分索引;低版本 MySQL(

  • 执行前确保 deleted_at 字段允许为 NULL(Laravel 迁移里要用 $table->softDeletes()->nullable())
  • 旧数据里 deleted_at = '0000-00-00 00:00:00' 或字符串 'null' 会导致索引失效,必须统一为 NULL
  • 别名索引名要唯一,避免和 Laravel 自动迁移生成的索引冲突(比如不要叫 users_email_unique)

Laravel 迁移中怎么安全加这个索引

不能直接在 Schema::create() 里写,得用 DB::statement() 手动建,因为 Laravel Schema 构建器不支持部分/函数索引。

laravel-specialist
laravel-specialist

精通 Laravel 10+,遵循现代 PHP 实践的 Laravel 专家。擅长优雅语法、Eloquent ORM、队列系统及企业级特性...

下载

推荐写法(适配 MySQL 和 PostgreSQL):

use Illuminate\Support\Facades\DB;
use Illuminate\Database\Migrations\Migration;

return new class extends Migration
{
    public function up(MigrationBuilder $migration): void
    {
        if (DB::getDriverName() === 'mysql') {
            DB::statement('CREATE UNIQUE INDEX user_email_active_unique ON users (email) WHERE deleted_at IS NULL');
        } elseif (DB::getDriverName() === 'pgsql') {
            DB::statement('CREATE UNIQUE INDEX user_email_active_unique ON users (email) WHERE deleted_at IS NULL');
        }
    }

    public function down(MigrationBuilder $migration): void
    {
        DB::statement('DROP INDEX user_email_active_unique');
    }
};
  • 别在 up() 里用 Schema::table(...)->unique(...),它生成不了带 WHERE 条件的索引
  • 如果项目同时跑 MySQL 和 PG,上线前务必确认对应库是否支持(MySQL
  • 加索引前先清理脏数据:UPDATE users SET deleted_at = NULL WHERE deleted_at = '0000-00-00 00:00:00';

查询时记得用 withTrashed() 或 onlyTrashed() 控制范围

索引改了,代码也得同步调整。否则会出现「数据库允许重复插入,但应用查不到刚插的软删记录」这种错位。

比如用户注册时校验邮箱是否已存在,应该用:

User::where('email', $email)->withoutTrashed()->exists()

而不是:

User::where('email', $email)->exists() // 默认就排除了软删记录,但得确认你没全局启用 withTrashed()
  • withoutTrashed() 是默认行为,但如果你在模型里写了 protected static $globalScopes = [...] 或调过 withTrashed(),就得显式恢复
  • 后台管理可能需要查全部(含软删),那就用 withTrashed(),但别忘了前端表单提交时仍要跳过软删记录做唯一校验
  • API 返回数据时,deleted_at 字段默认不会被隐藏,如果不想暴露,得在 toArray() 或资源类里手动 unset

真正麻烦的不是加索引,而是团队里有人忘了查数据时该不该包含软删记录,结果一个 find() 查到已注销用户,另一个 firstOrFail() 却抛出异常——边界模糊比语法错误更难 debug。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

laravel

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
laravel组件介绍
laravel组件介绍

laravel 提供了丰富的组件,包括身份验证、模板引擎、缓存、命令行工具、数据库交互、对象关系映射器、事件处理、文件操作、电子邮件发送、队列管理和数据验证。想了解更多laravel的相关内容,可以阅读本专题下面的文章。

2024.04.09

857

10

laravel中间件介绍
laravel中间件介绍

laravel 中间件分为五种类型:全局、路由、组、终止和自定。想了解更多laravel中间件的相关内容,可以阅读本专题下面的文章。

2024.04.09

855

9

laravel使用的设计模式有哪些
laravel使用的设计模式有哪些

laravel使用的设计模式有:1、单例模式;2、工厂方法模式;3、建造者模式;4、适配器模式;5、装饰器模式;6、策略模式;7、观察者模式。想了解更多laravel的相关内容,可以阅读本专题下面的文章。

2024.04.09

2508

10

thinkphp和laravel哪个简单
thinkphp和laravel哪个简单

对于初学者来说,laravel 的入门门槛较低,更易上手,原因包括:1. 更简单的安装和配置;2. 丰富的文档和社区支持;3. 简洁易懂的语法和 api;4. 平缓的学习曲线。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.10

4361

7

laravel入门教程
laravel入门教程

本专题整合了laravel入门教程,想了解更多详细内容,请阅读专题下面的文章。

2025.08.05

6330

22

laravel实战教程
laravel实战教程

本专题整合了laravel实战教程,阅读专题下面的文章了解更多详细内容。

2025.08.05

4176

13

laravel面试题
laravel面试题

本专题整合了laravel面试题相关内容,阅读专题下面的文章了解更多详细内容。

2025.08.05

7849

7

PHP高性能API设计与Laravel服务架构实践
PHP高性能API设计与Laravel服务架构实践

本专题围绕 PHP 在现代 Web 后端开发中的高性能实践展开,重点讲解基于 Laravel 框架构建可扩展 API 服务的核心方法。内容涵盖路由与中间件机制、服务容器与依赖注入、接口版本管理、缓存策略设计以及队列异步处理方案。同时结合高并发场景,深入分析性能瓶颈定位与优化思路,帮助开发者构建稳定、高效、易维护的 PHP 后端服务体系。

2026.03.04

1496

29

Laravel 框架安装指南
Laravel 框架安装指南

本指南详解 Laravel 框架安装全流程,涵盖 PHP 8.1+ 环境配置、Composer 依赖管理工具安装及国内镜像源优化。重点演示使用 composer create-project 命令创建 Laravel 10/11 项目,解决常见安装错误与依赖冲突。从环境搭建到项目初始化,助您快速完成 Laravel 开发环境部署,为后续 Web 应用开发奠定基础。适合 PHP 初学者与框架迁移开发者参考。

2026.04.09

215

6

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
如何安装 Composer
如何安装 Composer

共1课时 | 213人学习

Composer手册
Composer手册

共0课时 | 0人学习