Laravel使用Eloquent单查询批量插入后如何获取创建的模型实例?
方案1:自定义模型批量插入方法(适用于自增主键场景,性能最优)
仅需1次写入查询,无额外检索查询,前提是表主键为自增整数类型。
首先在对应模型(或通用基础模型)中新增静态方法:
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Facades\DB; class User extends Model { // 原有模型逻辑... public static function createMany(array $data): array { // 事务包裹避免并发写入导致主键不连续 return DB::transaction(function () use ($data) { // 按照create方法的逻辑预生成模型实例,自动遵守$fillable、$guarded批量赋值规则 $instances = collect($data)->map(fn ($item) => new static($item)); // 执行单查询批量插入 static::insert($instances->map->getAttributes()->toArray()); // 获取批量插入最后一条记录的自增ID $lastId = static::getConnection()->getPdo()->lastInsertId(); // 倒推所有记录的主键ID,给实例标记已写入状态 return $instances->sortByDesc(fn ($_, $index) => $index) ->map(function (Model $instance) use (&$lastId) { $instance->setAttribute($instance->getKeyName(), $lastId--); $instance->exists = true; return $instance; }) ->sortKeys() ->toArray(); }); } }
调用方式非常简单:
$users = User::createMany([ ['name' => 'Tom'], ['name' => 'Jerry'], ]); // 直接获取带主键的完整模型实例 echo $users[0]->id; // 输出第一条插入记录的主键
注意:InnoDB引擎下,单条INSERT语句批量插入的自增ID一定是连续的,该方案主键匹配不会出现错乱。
方案2:UUID/自定义非自增主键场景
如果使用UUID、雪花ID这类非自增主键,逻辑更简单,插入前提前生成主键即可,完全不需要额外查询:
$users = collect([ ['name' => 'Tom'], ['name' => 'Jerry'], ])->map(function ($item) { $user = new User($item); $user->id = str()->uuid(); // 提前生成自定义主键 return $user; }); // 批量插入 User::insert($users->map->getAttributes()->toArray()); // 标记实例已入库,直接使用 $users->each->setAttribute('exists', true);
方案3:小数据量临时方案
如果插入数据量极小(单次不超过10条),不想额外封装方法,可以直接遍历调用create,缺点是会产生N次写入查询,性能较低:
$users = collect([ ['name' => 'Tom'], ['name' => 'Jerry'], ])->map(fn ($item) => User::create($item))->toArray();
内容的提问来源于stack exchange,提问作者Nite
相关产品推荐
相关产品推荐

