使用Laravel Excel导入用户时如何检测文件内重复邮箱并抛出错误
需求实现方案
完全可以实现,你只需要在现有UsersImport类中增加导入文件内重复email校验逻辑即可,无需改动原有对外接口,修改方案如下:
核心思路
新增一个临时存储属性记录当前导入文件中已经处理过的邮箱,每次处理行数据时先做三重校验:
- 校验当前邮箱是否在导入文件中已经出现过
- 保留原有逻辑:校验当前邮箱是否已经存在于系统用户库中
- 校验通过后将当前邮箱存入临时属性,供后续行校验使用
完整修改后的代码
use Illuminate\Validation\Rule; class UsersImport implements ToModel, WithHeadingRow, WithValidation, WithBatchInserts, WithChunkReading { private $user; private $company; // 新增:存储导入文件中已出现的邮箱 private $importedEmails; public function __construct($user, $company) { $this->user = $user; $this->company = $company; // 初始化临时邮箱集合 $this->importedEmails = collect(); } public function model(array $row) { if(!isset($this->company)) return; // 新增:校验导入文件内是否有重复邮箱 if ($this->importedEmails->contains($row['email'])) { $this->throwNotification($row['email']." 在导入文件中重复存在。"); return; } if ($this->user->contains('email', $row['email'])) { $this->throwNotification($row['email']." 已在系统中存在。"); return; } // 校验通过,存入临时集合 $this->importedEmails->push($row['email']); Mail::to($row['email'])->send(new NewUser($this->company->name)); $employee = new \App\Models\User($row + [ 'company_id' => $this->company->id ]); return $employee; } public function rules(): array { return [ 'firstname' => 'required|string', 'lastname' => 'required|string', // 修复原代码的unique规则写法错误,且WithHeadingRow下无需加*.前缀 'email' => ['required', 'email', Rule::unique('users', 'email')], 'phone' => 'nullable|max:15', ]; } public function batchSize(): int { return 250; } public function chunkSize(): int { return 250; } }
额外注意事项
- 原代码中的验证规则写法有误:
unique|users:email是错误的分隔符写法,正确的规则写法为unique:users,email,使用Rule::unique语法可读性更高 - 如果你使用的是队列异步导入,需要注意分块处理时临时属性会被重置,这种场景下可以将已导入邮箱暂时存入缓存中做跨进程校验,同步导入场景下上述代码无需额外调整
- 临时集合
$importedEmails的生命周期和导入类实例一致,跨分块的行校验也能正常生效
内容的提问来源于stack exchange,提问作者George Dubedout
相关产品推荐
相关产品推荐

