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

Laravel删除项目时如何同步删除两个pivot中间表关联数据

实现级联删除方案

你可以通过修正模型关联定义+注册模型删除事件的方式实现需求,无需额外编写冗余的业务逻辑,具体实现如下:

1. 修正模型关联配置

你当前使用了自定义主键名(idp/idd/ida),belongsToMany 关联默认会按照「表名+_id」的规则自动匹配外键,不显式声明关联字段的话,后续关联查询、删除操作都会出错。

Project 模型调整

class Project extends Model
{
    protected $table = 'project';
    protected $primaryKey = 'idp';
    protected $fillable = ['pname'];

    // 关联Devis,显式指定中间表、外键、关联键
    public function devises()
    {
        return $this->belongsToMany(
            Devis::class,
            'devis_project', // 对应pivot中间表名
            'project_id',    // 中间表内关联Project的外键
            'devis_id'       // 中间表内关联Devis的外键
        );
    }

    // 注册模型删除事件,触发级联删除逻辑
    protected static function booted()
    {
        static::deleting(function (Project $project) {
            // 遍历当前项目下所有关联的Devis
            $project->devises()->each(function (Devis $devis) {
                // 清理Devis与Artical的中间表关联记录
                $devis->articals()->detach();
                // 删除当前Devis关联的所有Artical数据
                $devis->articals()->delete();
                // 删除Devis本身
                $devis->delete();
            });
            // 清理Project与Devis的中间表关联记录
            $project->devises()->detach();
        });
    }
}

注:这里保留了你原代码里的devises()方法名,不需要修改原有调用代码。

Devis 模型调整

class Devis extends Model
{
    protected $table = 'Devis';
    protected $primaryKey = 'idd';
    protected $fillable = ['type', 'lot', 'prix_total_avant_tax', 'tax_perse', 'tax_amount', 'prix_total_apre_tax', 'notes'];

    // 关联Artical,显式指定中间表、外键、关联键
    public function articals()
    {
        return $this->belongsToMany(
            Artical::class,
            'artical_devis', // 对应pivot中间表名
            'devis_id',      // 中间表内关联Devis的外键
            'artical_id'     // 中间表内关联Artical的外键
        )->withPivot('qte', 'total');
    }
}

Artical 模型无需调整,保留原有代码即可

class Artical extends Model
{
    protected $table = 'artical';
    protected $primaryKey = 'ida';
    protected $fillable = [ 'num_art' , 'designation', 'unite','prix_unit'];
}

2. 使用方式

配置完成后,正常调用删除方法即可自动同步清理所有关联数据:

// 查找对应项目
$project = Project::find($projectId);
// 执行删除,关联的Devis、Artical、两张中间表记录都会自动清理
$project->delete();

注意事项

  • 如果你的项目使用了SoftDeletes软删除功能,需要额外监听forceDeleting事件,否则强制删除数据时不会触发上述级联逻辑。
  • 如果Artical条目会被多个Devis共享,不要执行$devis->articals()->delete()删除Artical本体,只保留detach()清理中间表关联即可,避免误删其他报价单正在使用的条目。
  • 如果单项目下关联的Devis、Artical数据量很大,可以把遍历方法从each()换成cursor(),用游标遍历减少内存占用。
  • 最稳妥的级联方案是直接在数据库层设置外键ON DELETE CASCADE规则,给两张中间表、Devis表的关联外键配置级联删除后,哪怕直接操作数据库删数据,也不会产生孤立的脏数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 09:27:28