本地作用域必须返回 $query 实例才能维持链式调用,方法需以 scope 开头、声明为 public,且不可访问 $this 实例属性;带参作用域须严格类型声明并处理空值,避免传入请求上下文对象。

本地作用域怎么写才不会断链式调用
本地作用域必须返回 $query,否则后续的 where、orderBy 会直接报错或静默失效。Eloquent 在调用时自动把当前 Builder 实例传入第一个参数,你不能把它当普通实例方法来用。
- 错误写法:
public function scopeActive($query) { $query->where('status', 'active'); }—— 少了return - 正确写法:
public function scopeActive($query) { return $query->where('status', 'active'); } - 别在作用域里访问
$this->id或其他模型实例属性 —— 此时模型还没从数据库加载出来 - 方法必须是
public,且命名严格以scope开头(如scopeLatest),调用时写->latest()
带参数的作用域为什么总报错
参数类型不匹配、空值未处理、或传了不该传的对象,是本地作用域最常翻车的地方。PHP 8+ 的严格类型检查会让这类问题立刻暴露,但低版本可能只在运行时崩掉。
- 明确声明类型:
public function scopeWithinDays($query, int $days = 7),避免传字符串'30'导致subDays()报错 - 对可为空参数做兜底:
public function scopeByCategory($query, ?string $category = null) { return $category ? $query->where('category', $category) : $query; } - 别传
Request或Auth实例进作用域 —— 本地作用域不是控制器,不该耦合请求上下文 - 测试时用
User::where('name', 'test')->byCategory('admin')->get()直接验证,比写单元测试更快定位参数问题
全局作用域为什么在队列里查不到数据
全局作用域在 CLI 或队列任务中拿不到 HTTP 请求上下文,硬编码从 session() 或 request() 取租户 ID,必然导致条件为空或报错。
Laravel Cloud(cloud.laravel.com)。此技能用于处理所有 Laravel Cloud 请求,包括搜索和读取数据。只要任务涉及 Laravel Cloud,即使用此技能。
- 租户 ID 必须通过服务容器解析(如
app(TenantManager::class)->currentId()),这个类需支持 CLI 环境下的 fallback 逻辑 - 不要在
apply()里写whereNotNull('tenant_id')这类兜底 —— 它会污染真实查询,让forceDelete()也带上条件 -
remove()方法不是摆设:数据迁移时用Model::withoutGlobalScopes()->get(),但得确保它真能跳过你的全局作用域(有些实现漏写了remove()) - 全局作用域不适用于软删除:Laravel 自带的
SoftDeletestrait 已内置控制逻辑,再加一层全局whereNull('deleted_at')会导致restore()失效
scopeWithoutTrashed 这类自定义软删除作用域怎么防误用
直接在作用域里写 whereNull('deleted_at') 很危险 —— 如果模型没用 SoftDeletes trait,这个条件就变成无意义的过滤,还可能掩盖业务逻辑错误。
- 必须加保护判断:
if (static::usesSoftDelete()) { $query->whereNull('deleted_at'); } - 别在
boot()里用addGlobalScope()强制加软删除条件 —— 官方明确反对,restore()和后台列表都会出问题 - 日常就用
Model::withoutTrashed(),它已内置安全判断;只有需要封装语义(比如叫scopePublished())才自己写作用域 - 如果同时用了
scopeWithoutTrashed()和withoutTrashed(),SQL 里会出现两个WHERE deleted_at IS NULL,查不到数据却很难排查
真正难的不是写对一个作用域,而是保证它在命令行、队列、API、后台管理多个上下文中行为一致。全局作用域尤其容易在非 HTTP 场景下静默失效,本地作用域则常因参数校验松散引发线上异常 —— 这些地方没日志、没提示,只能靠测试覆盖和调用习惯卡死。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










