什麼是 PHP Attributes
PHP Attributes 是 PHP 8.0 導入的原生 metadata 語法。可對類別、方法、屬性、函式等以#[AttributeName] 形式加註元資訊。
Laravel 於框架本體積極採用 PHP Attributes,可以宣告式撰寫 Job 或 Eloquent 模型的設定。於 Laravel 13(v13.2.0)中,Queue attribute 可接受 enum。相較於傳統的類別屬性或方法覆寫,使用 attribute 可寫出更易讀且簡潔的程式碼。
Queue 相關 Attributes
Queue Job 相關的 attributes 皆位於Illuminate\Queue\Attributes 命名空間。
#[Queue] — 指定 Queue 名稱
指定 Job 送往的預設 Queue 名稱。
#[Queue] attribute 的 target 被設為 Attribute::TARGET_CLASS,因此只能套用於類別。#[Connection] — 指定 Connection
指定 Job 使用的預設 Queue Connection。
#[Backoff] — 指定重試 backoff 時間
指定 Job 失敗時,重試前的等待時間(秒)。傳入多個值時,每次重試可設定不同的等待時間(可變長引數支援)。
Backoff 類別的實作,設計為接受可變長引數。
int 存放,多個值時作為 array 存放。
#[Tries] — 指定重試次數
指定 Job 失敗時的最大重試次數。
#[Timeout] — 指定 Timeout
指定 Job 的最大執行時間(秒)。超過此時間時,Job 會被強制中止。
#[MaxExceptions] — 指定容許例外次數
當發生指定次數以上的例外時,將 Job 視為失敗。搭配 #[Tries] 使用。
#[UniqueFor] — 指定唯一期間
指定防止 Job 重複執行的 lock 期間(秒)。搭配 ShouldBeUnique 使用。
#[DeleteWhenMissingModels] — 模型不存在時刪除
當 Job 相依的 Eloquent 模型找不到時,將 Job 視為刪除(跳過)而非失敗。
#[WithoutRelations] — 排除關聯
於 Job 序列化時不將模型的關聯納入。可精簡送往 Queue 的資料量。
#[FailOnTimeout] — Timeout 時視為失敗
當發生 Timeout 時,將 Job 記錄為失敗(預設 Timeout 不會被記錄為失敗)。
組合多個 Queue Attributes
可以組合這些 attribute,宣告式設定 Job 的行為。Eloquent 相關 Attributes
Eloquent 模型的 attributes 位於Illuminate\Database\Eloquent\Attributes 命名空間。Laravel 13 新增了大量 attribute。
#[ScopedBy] — 指定 Global Scope
以 attribute 指定要自動套用至模型的 Global Scope 類別。支援繼承,並具有 IS_REPEATABLE 旗標,可指定多個 Scope。
booted() 方法的比較。
#[ObservedBy] — 指定 Observer
以 attribute 指定關聯至模型的 Observer 類別。與 ScopedBy 同樣為 IS_REPEATABLE。
AppServiceProvider 註冊。
#[UseEloquentBuilder] — 指定自訂 Query Builder
以 attribute 指定模型所使用的自訂 Eloquent Builder。
#[CollectedBy] — 指定自訂 Collection
以 attribute 指定模型的 Collection 所使用的自訂 Collection 類別。
#[Table] — 一次指定 Table 相關設定
可以一個 attribute 一次指定表格名稱、主鍵、時間戳記等多個 Table 相關設定。
Table attribute 可設定的選項如下。
#[Scope] — 將方法定義為本地 Scope
可將不含 scope 前綴的方法定義為 Eloquent 的本地 Scope。
#[UseFactory] — 指定 Factory 類別
以 attribute 指定模型所使用的自訂 Factory 類別。
其他 Eloquent Attributes
Enum 支援(於 v13.2.0 加入)
於 v13.2.0,#[Queue] 與 #[Connection] 開始接受 enum。如此便可使用 PHP enum 取代字串字面值,型別安全地指定 Queue 與 Connection。
與傳統類別屬性的比較
Attribute 的優點
- 宣告式 — 觀察類別開頭即可一眼看出 Job 的行為
- 型別安全 — 使用 enum 可享有 IDE 補完與型別檢查
- 與繼承的親和性 — 父類別的 attribute 可於子類別覆寫
- 減少程式碼 — 不需宣告屬性或覆寫方法
Attribute 的缺點
- 無法設定動態值 — attribute 的引數僅能為編譯時常數。無法使用變數或設定檔的值
- 需適應 — 團隊有時需要適應 PHP 8 的 attribute 語法
需要動態值時
若希望於執行時決定值,仍使用傳統的方法覆寫。實作機制
Laravel 內部使用 Reflection API 讀取 attribute。當 Queue Worker dispatch Job 時,ReadsQueueAttributes trait(包含於 InteractsWithQueue 中)以 reflection 偵測 attribute,並將值設定至對應屬性。
Model::booted() 的時機以 reflection 讀取。
下一步
中階:Queue 與 Job
學習 Laravel Queue 系統的基本用法。
PHP Reflection API
詳細說明 Laravel 讀取 attribute 所使用的 Reflection API 機制。