Laravel中Model::create()在Chrome重复/乱序入库,Edge正常,求解析
问题解析与解决方案
核心原因:GET请求特性+Chrome重试行为触发
浏览器本身不会直接干扰Laravel ORM的执行逻辑,你遇到的差异本质是Chrome对GET请求的重试机制被触发,而非Zone::create()本身有异常:
- HTTP规范中GET请求被定义为「幂等请求」,Chrome会在检测到GET请求响应超时、未完成时自动发送重试请求,导致你的路由闭包代码被多次执行,进而重复插入数据。
- Edge在你的测试场景下未触发重试逻辑,所以表现正常。
Zone::create()与save()的差异诱因
两者本质都是模型保存,但create()会额外处理:
- 批量赋值校验(你其他场景能用说明
$fillable配置正常) - 触发
creating/created模型事件
这些额外逻辑会增加请求处理时间,刚好达到Chrome的重试阈值,触发重复请求;而手动实例化+save()的流程更简洁,处理速度更快,未触发Chrome重试,所以表现稳定。
findCompany函数的潜在优化点
你当前的findCompany用了Collection的where方法:
->shippings->where('company',$company)
这会先把当前Production的所有shippings数据加载到内存再过滤,数据量大时会显著增加处理时间,进一步提升Chrome触发重试的概率。改成关联查询构造器可以直接在数据库层面过滤,减少耗时:
function findCompany($company,$country) { return Production::where('country',$country) ->first() ->shippings() // 加()使用关联查询构造器 ->where('company',$company) ->first() ->id; }
最终解决方案
- 替换GET路由为非幂等请求:
数据插入/修改操作必须用POST/PUT/DELETE等非幂请求,浏览器不会自动重试这类请求。修改路由:
通过表单或AJAX发送POST请求触发数据填充。Route::post('/admin-panel/zones-add', function () { // 原有逻辑 }); - 重构代码结构:避免在路由闭包里定义内部函数,将
zoneMake、findCompany抽成控制器方法或服务类,提升代码可维护性。
内容的提问来源于stack exchange,提问作者Manny
相关产品推荐
相关产品推荐

