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

使用Queue时如何获取Laravel Excel导入的验证失败信息

队列模式下Laravel Excel获取导入失败记录的解决方案

当导入类实现ShouldQueue接口后,SkipsFailures trait中存储的失败数据无法在AfterImport事件中获取——原因是队列任务在独立进程执行,内存中的临时数据会随进程结束释放,且序列化后的导入实例无法保留这些内存数据。

解决方法:持久化失败记录到数据库

通过将每条验证失败的记录存储到数据库,在AfterImport事件中从数据库查询获取失败数据,具体步骤如下:

  1. 创建失败记录的数据库表
    生成迁移文件并执行:
Schema::create('import_failures', function (Blueprint $table) {
    $table->id();
    $table->unsignedBigInteger('user_id');
    $table->string('import_type'); // 标记导入类,比如App\Imports\ProductImport
    $table->integer('row'); // 失败的行号
    $table->json('errors'); // 错误信息数组
    $table->string('import_id')->nullable(); // 唯一标识单次导入,区分同用户的不同导入任务
    $table->timestamps();

    $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
  1. 创建对应模型
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class ImportFailure extends Model
{
    protected $fillable = ['user_id', 'import_type', 'row', 'errors', 'import_id'];
    protected $casts = ['errors' => 'array'];
}
  1. 修改导入类逻辑
    在导入类中实现onFailure方法存储失败记录,同时在AfterImport事件中查询数据库获取失败数据:
use App\Models\ImportFailure;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithValidation;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Events\AfterImport;
use Illuminate\Contracts\Queue\ShouldQueue;
use Maatwebsite\Excel\Concerns\SkipsOnFailure;
use Maatwebsite\Excel\Concerns\SkipsFailures;
use Maatwebsite\Excel\Validators\Failure;
use Maatwebsite\Excel\Concerns\WithBatchInserts;
use Maatwebsite\Excel\Concerns\WithChunkReading;
use Maatwebsite\Excel\Concerns\WithHeadingRow;

class ProductImport implements ToModel, WithValidation, WithEvents, WithBatchInserts, WithChunkReading, WithHeadingRow, ShouldQueue, SkipsOnFailure
{
    use SkipsFailures;

    protected $user;
    protected $importId;

    public function __construct($user)
    {
        $this->user = $user;
        $this->importId = uniqid('product_import_'); // 生成单次导入的唯一标识
    }

    // 捕获验证失败,存储到数据库
    public function onFailure(Failure ...$failures)
    {
        foreach ($failures as $failure) {
            ImportFailure::create([
                'user_id' => $this->user->id,
                'import_type' => self::class,
                'row' => $failure->row(),
                'errors' => $failure->errors(),
                'import_id' => $this->importId
            ]);
        }
    }

    public function registerEvents(): array
    {
        return [
            AfterImport::class => function(AfterImport $event) {
                // 查询本次导入的所有失败记录
                $failures = ImportFailure::where('user_id', $this->user->id)
                    ->where('import_type', self::class)
                    ->where('import_id', $this->importId)
                    ->get();

                // 统计成功导入数量(需根据实际导入逻辑实现,例如可在ToModel中计数并存入临时表或缓存)
                $importedCount = 0; // 替换为实际统计逻辑

                $this->user->notify(new ImportCompleted($importedCount, $failures));
            },
        ];
    }

    // 其他必要方法(ToModel、rules等)请自行补充
}

额外说明

  • 如果不需要持久化失败记录,也可以使用Redis缓存临时存储失败数据,但数据库存储更可靠,不会因缓存过期或清理丢失数据。
  • 成功导入数量的统计需要结合你的业务逻辑实现,例如在ToModel方法中记录创建成功的模型数量,存入数据库或缓存后在AfterImport中读取。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 04:55:35