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

Laravel软删除迁移单元测试失败问题求助

Laravel软删除迁移导致单元测试失败的解决方案

问题背景

为现有Inclusion模型添加软删除功能后,本地及预发布环境运行正常,但单元测试(每次重建数据库并执行所有迁移)报错,提示找不到deleted_at列。原因在于:

  1. 旧迁移中使用Eloquent查询inclusions表时,模型已启用软删除特性,会自动拼接WHERE deleted_at IS NULL条件;
  2. 软删除的迁移(添加deleted_at列)执行顺序在旧迁移之后,导致旧迁移执行时数据库中尚未存在该列,SQL查询触发报错。

可行解决方案

方案1:修改旧迁移,临时关闭软删除作用域

针对那个同步inclusion_vertical数据的旧迁移,将Eloquent查询替换为不带软删除全局作用域的版本,避免查询时引用不存在的deleted_at列:

// 替换原有的 Inclusion::each(...)
Inclusion::withoutGlobalScopes(['Illuminate\Database\Eloquent\SoftDeletingScope'])->each(function (Inclusion $inclusion) use ($verticals) {
    $verticalIds = json_decode($inclusion->getAttribute('verticals'));
    $inclusion->verticals()->sync($verticals->whereIn('external_id', $verticalIds));
});

更稳妥的方式是直接使用数据库查询构建器,完全绕开模型的软删除约束:

$verticals = Vertical::all()->pluck('id', 'external_id');

DB::table('inclusions')->each(function ($row) use ($verticals) {
    $verticalIds = json_decode($row['verticals']);
    $matchingVerticalIds = $verticals->intersect($verticalIds)->values()->all();
    
    foreach ($matchingVerticalIds as $verticalId) {
        DB::table('inclusion_vertical')->insert([
            'inclusion_id' => $row['id'],
            'vertical_id' => $verticalId,
        ]);
    }
});

方案2:在模型中动态关闭迁移场景下的软删除

在Inclusion模型中添加逻辑,检测到当前处于迁移执行状态时,自动禁用软删除作用域:

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Scope;

class Inclusion extends Model
{
    use SoftDeletes;

    protected static function booted()
    {
        // 判断是否在执行迁移命令
        if (app()->runningInConsole() && in_array(request()->command(), ['migrate', 'migrate:fresh'])) {
            // 移除默认的软删除作用域
            static::removeGlobalScope('Illuminate\Database\Eloquent\SoftDeletingScope');
            // 添加空作用域替代,避免原有逻辑冲突
            static::addGlobalScope(new class implements Scope
            {
                public function apply(Builder $builder, Model $model)
                {
                    // 无额外查询条件
                }
            });
        }
    }
}

注意事项

  • 不要修改旧迁移的Schema定义(比如在初始迁移中添加softDeletes()),生产环境已执行过该迁移,修改会导致迁移失败;但修改迁移中的数据操作部分是安全的,生产环境不会重复执行已完成的迁移。
  • 所有方案均无需区分测试与生产环境,保持代码一致性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 10:31:28