onBeforeInsert仅在模型save()、create()中触发,需用self::event('before_insert')注册并返回false中断;Db::insert等原生操作不触发,且不支持批量插入。

onBeforeInsert 不会在 Db::insert() 或原生 SQL 中触发,只对模型的 save()、create() 等写入方法生效。
新增前事件只在模型层有效
如果你用 Db::name('article')->insert($data),onBeforeInsert 完全不会执行。它只绑定在模型类上,且依赖模型的写入流程。想拦截新增,必须走模型实例或静态调用:Article::create($data) 或 (new Article())->save($data)。
-
onBeforeInsert是静态方法,接收一个$model实例(尚未入库) - 它不支持返回
false阻断操作(TP6 中需改用event()注册方式才能中断) - 若需校验失败后中止新增,推荐用
self::event('before_insert', function($model) { ... return false; })
用 self::event() 替代静态方法更可控
直接在模型 init() 中注册事件,能精确控制中断逻辑和参数访问:
public static function init()
{
self::event('before_insert', function($model) {
if (empty($model['title'])) {
return false; // 中断新增
}
$model['slug'] = \think\facade\Str::slug($model['title']);
$model['created_at'] = date('Y-m-d H:i:s');
});
}
- 闭包内可修改
$model属性,这些变更会进入后续写入流程 - 返回
false会直接终止本次save()或create() - 注意:该事件不触发于批量插入(
saveAll()默认不触发单条事件)
常见踩坑点:字段赋值时机与事务冲突
在 before_insert 里给字段赋值,如果字段是数据库自增主键(如 id),或设置了默认值(如 created_at DEFAULT CURRENT_TIMESTAMP),手动赋值可能被忽略或引发唯一冲突。
- 避免覆盖数据库级默认行为,比如不要在事件里硬设
$model['id'] = ... - 若涉及关联表写入(如先插主表再记日志),记得确认当前是否已开启事务——
before_insert在事务内执行,但日志表操作若没显式加入同一事务,可能提交失败后残留 - 调试时用
dump($model->getData())查看实际传入数据,别只看原始$data数组
self::event() 注册。其余方式不是失效就是难调试。



















