thinkphp3.2的addall()仅支持批量插入,不支持批量替换;需通过原生sql(replace into或insert ... on duplicate key update)、事务删插组合或逐条save()实现,且需注意字段顺序一致性。

ThinkPHP3.2 的 addAll() 方法本身不支持批量替换(即“存在则更新,不存在则插入”)功能,它只是单纯的批量插入。如果你传入的数据中某条记录的主键或唯一索引已存在,数据库会直接报错(如 MySQL 的 Duplicate entry),而框架不会自动转为 REPLACE INTO 或 INSERT ... ON DUPLICATE KEY UPDATE。
但你可以通过以下方式间接实现“批量替换”效果:
-
用原生 SQL 手动执行
REPLACE INTO或INSERT ... ON DUPLICATE KEY UPDATE
ThinkPHP3.2 支持$Model->execute(),可直接运行带事务的多条语句:$sql = "REPLACE INTO tp_user (id, name, email) VALUES (1,'a','a@b.com'),(2,'b','b@b.com')"; $model = M('user'); $model->execute($sql); -
结合事务 + 先删后插(适合小数据量、主键明确场景)
$ids = array_column($dataList, 'id'); $model->where(['id' => ['in', $ids]])->delete(); // 先清旧 $model->addAll($dataList); // 再全量插入
-
逐条判断 +
save()(性能较差,仅适用于几十条以内)
利用模型的create()和save()自动识别主键是否存在:foreach ($dataList as $data) { $model->create($data, Model::MODEL_BOTH); $model->save(); // 主键存在则更新,不存在则插入 } -
注意
addAll()的坑:数组键名必须对齐
如果$dataList中每条记录的键顺序不一致(比如有的'name'在前,有的在后),可能导致字段错位。建议插入前统一ksort():array_walk($dataList, function(&$item) { ksort($item); });
本质上,ThinkPHP3.2 没有封装 upsert 类方法,所谓“批量替换”需自行组合逻辑或绕过 ORM 直接操作 SQL。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











