tp6模型必须严格遵循路径app\model\user.php、命名空间app\model、继承think\model三要素,否则报类未找到;表名非user或主键非id需显式配置$table和$pk;find()/select()返回对象而非数组,须用->访问属性。

User 模型必须继承 think\Model,放在 app\model\ 目录下,类名首字母大写且默认映射表名小写(如 User → user),否则会报 Class 'app\model\User' not found。这不是“怎么写更优雅”的问题,而是路径、命名、继承三者缺一不可的硬性前提。
模型类怎么定义才不会报错
常见错误是新建了 User.php 却放在 application/model/ 或 app/Model/(大小写错),或类名写成 user、Users、UserModel。TP6+ 严格按 PSR-4 规范自动加载,路径和命名必须完全匹配。
如果表名不是 user,比如叫 tb_user,必须显式声明:
protected $table = 'tb_user';主键不是
id 时(如 user_id),也要加:protected $pk = 'user_id';不设
$pk 会导致 save() 更新失败、destroy() 找不到主键条件。
- 模型文件路径只能是
app\model\User.php - 命名空间必须是
namespace app\model; - 类必须
extends \think\Model,不能只写Model -
$table和$pk是最常漏配的两个属性,尤其在迁移旧项目时
查数据:find() 和 select() 返回值不是数组
find() 返回单个 think\Model 实例,select() 返回 think\Collection(可遍历对象,不是数组)。直接 echo $user['name'] 或 $users[0]['name'] 会报错,必须用对象语法:$user->name 或 $users[0]->name。
复合查询别用 find(['status'=>1]),它语义模糊且 TP6+ 已不推荐;统一走链式:
User::where('status', 1)->find();
field() 不显式声明,聚合字段或别名会被过滤掉:User::field('id, name, COUNT(*) as total')->group('status')->select();
- 软删除模型(用了
SoftDeletetrait)默认不查已删除记录,要查得加withTrashed() -
all()是静态方法,等价于select(),但语义更明确 - 分页必须用
paginate(),不能对select()结果手动切片
增删改:save() 必须带数据,create() 不再接受空参数
save() 不再支持无参调用,空模型实例调用会静默失败。必须先 data() 赋值,或构造时传数组:
$user = new User();<br>$user->data(['name' => '张三']);<br>$user->save();或者一步到位:
User::create(['name' => '李四']);注意
create() 会触发验证和事件,save() 不会(除非显式调用 validate(true))。
批量插入用 saveAll(),参数是二维数组:
User::saveAll([<br> ['name' => 'A'],<br> ['name' => 'B']<br>]);删除和更新必须带
where 条件,User::destroy(1) 底层仍是 where($pk, 1)->delete(),没 where 就是全表删。
-
update()方法只接受数组,不能用于模型实例:$user->update(['name'=>'X'])是错的,得用$user->save(['name'=>'X']) -
destroy()支持 ID、数组、闭包条件,但闭包里不能用$this(无上下文) - 更新时若只改部分字段,记得
allowField()控制白名单,防意外覆盖
Db 类和 Model 类根本不是一回事
用 Db::name('user')->select() 是查询构建器操作,返回纯数组,不走模型验证、事件、自动完成、类型转换。它快、轻量,适合报表、统计、临时查。但只要业务逻辑涉及数据校验、状态变更钩子、关联预载,就必须用 User::where(...)->select() 这类模型操作。
混用容易踩坑:比如在模型里用 Db::insert() 插入数据,就不会触发 before_insert 事件;用 User::create() 但忘了配 $autoWriteTimestamp,create_time 字段就为空。
- 模型操作默认开启时间戳写入(
auto_timestamp配置控制),Db不管这个 - 字段类型自动转换(如
int字段返回整数而非字符串)只在模型层生效 - 关联查询(
with('profile'))必须走模型,Db只能手写join
$pk 忘设、查出来当数组用、或误把 Db 当模型使——这些地方不报红,但数据不对、事件不触发、字段不转类型,debug 成本远高于写代码本身。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











