什么是 PHP 属性
PHP 属性(PHP Attributes)是 PHP 8.0 引入的原生元数据语法。可以对类、方法、属性、函数等以#[AttributeName] 形式附加元信息。
Laravel 在框架内部积极采用 PHP 属性,可以以声明式的方式配置 Job 与 Eloquent Model。Laravel 13(v13.2.0)中队列属性还开始接受 enum。相较于以往通过类属性或方法覆写来设置,使用属性可以写出更易读、更简洁的代码。
队列相关属性
队列 Job 相关的属性都位于Illuminate\Queue\Attributes 命名空间。
#[Queue] — 指定队列名
指定 Job 派发的默认队列名。
#[Queue] 属性的 target 被设置为 Attribute::TARGET_CLASS,因此只能用在类上。#[Connection] — 指定连接
指定 Job 使用的默认队列连接。
#[Backoff] — 指定重试的退避时间
指定 Job 失败后重试前的等待时间(秒)。可传多个值为不同次重试指定不同等待时间(支持可变参数)。
Backoff 类的实现,它接收可变参数。
int,多值时保存为 array。
#[Tries] — 指定重试次数
指定 Job 失败时的最大重试次数。
#[Timeout] — 指定超时时间
指定 Job 的最大执行时间(秒),超过则会被强制终止。
#[MaxExceptions] — 指定允许的异常次数
发生指定次数以上的异常时,将 Job 视为失败。通常与 #[Tries] 搭配使用。
#[UniqueFor] — 指定唯一周期
指定阻止 Job 重复执行的锁定周期(秒)。与 ShouldBeUnique 一起使用。
#[DeleteWhenMissingModels] — 模型不存在时删除
当 Job 依赖的 Eloquent 模型不存在时,将该 Job 视为删除(跳过)而不是失败。
#[WithoutRelations] — 排除关联
在 Job 序列化时不包含模型的关联,可以让入队数据更小。
#[FailOnTimeout] — 超时视为失败
发生超时时把 Job 记录为失败(默认情况下超时不会记录为失败)。
组合多个队列属性
将这些属性组合可以以声明方式配置 Job 的行为。Eloquent 相关属性
Eloquent 模型属性位于Illuminate\Database\Eloquent\Attributes 命名空间。Laravel 13 中新增了大量属性。
#[ScopedBy] — 指定全局作用域
以属性形式指定要自动应用到模型上的全局作用域类。支持继承,通过 IS_REPEATABLE 标志可以指定多个作用域。
booted() 方法对比。
#[ObservedBy] — 指定 Observer
以属性形式指定模型关联的 Observer 类。与 ScopedBy 一样是 IS_REPEATABLE。
AppServiceProvider 中注册。
#[UseEloquentBuilder] — 指定自定义 Query Builder
以属性形式指定模型所使用的自定义 Eloquent Builder。
#[CollectedBy] — 指定自定义 Collection
以属性形式指定模型作为集合时使用的自定义 Collection 类。
#[Table] — 一次指定表相关配置
在一个属性中指定表名、主键、时间戳等多个表相关配置。
Table 属性可配置的选项如下。
#[Scope] — 将方法定义为本地作用域
可以把没有 scope 前缀的方法定义为 Eloquent 本地作用域。
#[UseFactory] — 指定 Factory 类
以属性形式指定模型使用的自定义 Factory 类。
其他 Eloquent 属性
Enum 支持(v13.2.0 新增)
在 v13.2.0 中,#[Queue] 与 #[Connection] 开始接受 enum。你可以用 PHP enum 而非字符串字面量来类型安全地指定队列与连接。
与传统类属性的对比
属性的优点
- 声明式 — 一眼就能看出 Job 的行为
- 类型安全 — 使用 enum 能获得 IDE 补全与类型检查
- 与继承兼容 — 子类可覆盖父类的属性
- 代码更精简 — 无需属性声明或方法覆写
属性的缺点
- 不能设置动态值 — 属性参数只能是编译期常量,无法使用变量或配置文件的值
- 需要熟悉 — 团队可能需要熟悉 PHP 8 的属性语法
需要动态值时
想在运行时决定值时,仍使用传统的方法覆写。实现机制
Laravel 内部使用 Reflection API 读取属性。当 Queue Worker 派发 Job 时,ReadsQueueAttributes trait(包含在 InteractsWithQueue 中)会通过反射发现属性并把值写入相应属性。
Model::booted() 对应时机被读取。
下一步
中级:队列与 Job
学习 Laravel 队列系统的基本用法。
PHP Reflection API
详解 Laravel 用于读取属性的 Reflection API 的机制。