thinkphp模型的create()方法不支持批量创建,仅用于单条数据验证与构造;批量应使用saveall()(需模型逻辑时)或db::insertall()(纯写入场景),且大批量须分片加事务。

别指望 create() 批量,它只服务单条
`create()` 的设计目标是「从原始输入(如 $_POST)中安全提取并构造一条有效数据」,流程包括字段过滤、验证、自动完成、时间戳填充等。它返回的是一个模型实例或布尔值,不是数据数组,更不接受二维数组输入。
常见错误写法:
$User->create($dataArray); // $dataArray 是二维数组 → 直接报错或只取第一行User::create($dataList); // 静态调用 + 多条数据 → 不生效,甚至触发严格模式异常
如果你硬要在循环里反复调 `create()` 再 `save()`,那就是 N 次查询+验证,性能极差,还容易超时、爆内存——这不是批量,是反模式。
批量创建请用 saveAll()(需模型逻辑时)
当你要保留模型的时间戳、验证、自动写入、事件钩子(如 before_insert)时,`saveAll()` 是唯一正解。但它不是 `create()` 的升级版,而是独立方法,调用前无需也不应先调 `create()`。
正确写法:
- 复用一个模型实例(避免反复 new):
$user = new User();<br> $result = $user->saveAll($dataList, ['validate' => false, 'batch' => true]);
- 必须传二维数组,每项键名严格对应数据库字段(如
['name'=>'张三','email'=>'z@x.com']) -
['batch' => true]是关键参数,否则默认逐条执行,失去批量意义 -
['validate' => false]在数据已清洗干净时建议加上,跳过验证能明显提速
注意:`saveAll()` 成功后,若主键为自增整型,会返回插入的 ID 数组;否则返回 true 或 false。
纯写入场景用 Db::insertAll()(更快更轻)
如果只是把结构规整的数据塞进表里,不需要验证、不关心钩子、不依赖模型逻辑(比如后台导入、日志归档、定时同步),那就绕过模型,直连数据库:
$result = Db::name('user')->insertAll($dataList);- 字段名必须 100% 匹配数据库列名(模型里的
type转换、JSON 自动序列化等功能全部失效) - 时间戳字段(如
create_time)要自己写进数组:['name'=>'李四', 'create_time'=>date('Y-m-d H:i:s')] - 返回值是影响行数(int),失败抛异常,不是
false—— 别用if($result)判定成功
大批量务必分片 + 事务包裹
不管用 `saveAll()` 还是 `insertAll()`,一次性处理超过 500 条都风险很高(MySQL 报 Packets larger than max_allowed_packet、PHP 内存溢出、Web 请求超时)。必须主动拆分:
- 用
array_chunk($dataList, 400)拆成每批 400 条 - 显式开启事务:
Db::transaction(function () use ($chunks) {<br> foreach ($chunks as $chunk) {<br> Db::name('user')->insertAll($chunk);<br> }<br> }); - CLI 脚本加
set_time_limit(0);Web 端强烈建议改用队列处理 - 每批执行后调
gc_collect_cycles(),防止大数组驻留内存
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











