直接 new 模型类实例是错误的起点,会绕过 Eloquent 生命周期、事件、访问器、casts、boot()、全局作用域及软删除机制;应优先使用静态查询方法(如 find、where、firstOrFail、with),或依赖注入、正确区分 static/instance 方法调用。

直接 new 模型类实例是错的起点
很多刚接触 Laravel 5.5 的人会照着旧教程写 new Article() 或 new User(),这看似能跑通,但会绕过 Eloquent 的生命周期、事件、访问器(accessors)、强制类型转换(casts)等核心机制。更严重的是,它无法触发模型的 boot() 静态方法、全局作用域(global scopes),也不受软删除(SoftDeletes trait)约束——查出来的数据可能包含已被“删除”的记录。
推荐写法:用静态查询方法代替 new 实例
绝大多数场景下,你应该用模型自带的静态方法,而不是手动 new:
-
User::find(1)—— 安全获取单条,自动应用软删除过滤 -
User::where('status', 'active')->get()—— 返回集合,支持链式调用和事件 -
User::firstOrFail()—— 找不到直接抛异常,避免空对象后续报错 -
User::with('posts')->get()—— 预加载关联,避免 N+1 查询
这些调用背后由 Laravel 的服务容器管理,保证了模型行为的一致性和可测试性。如果你非得手动实例化(比如构造一个待保存的新对象),也应仅用于 new User() 后立即 ->save(),且不能用于查询。
依赖注入模型实例(适用于路由模型绑定)
当控制器方法参数名与路由参数名一致,且类型提示为对应模型时,Laravel 会自动执行模型查找并注入:
Route::get('/users/{user}', 'UserController@show');
对应控制器中:
public function show(User $user)
{
// $user 已是已查出的 User 实例,且自动应用了软删除、全局作用域等
return view('user.show', compact('user'));
}
注意:$user 是 Eloquent 实例,不是 ID;如果数据库无匹配记录,会自动返回 404,无需手动 findOrFail。
调用模型里的自定义方法要注意 static 和 instance 区别
模型里写的方法,调用方式取决于定义方式:
- 静态方法(
public static function getStatusList())→ 必须用User::getStatusList() - 实例方法(
public function getFullName())→ 只能用在实例上:$user->getFullName(),不能User::getFullName(),否则报Non-static method should not be called statically - 作用域(scope)方法(
public function scopeActive($query))→ 必须配合查询构建器:User::active()->get(),不能直接调用$user->active()
容易被忽略的是:模型里定义的常量(如 const STATUS_DRAFT = 0)可以直接用 User::STATUS_DRAFT 访问,但私有/受保护常量不行。











