考慮以下情境:你有一個用戶模型$user ,包含了很多字段,例如ID、姓名、郵箱、密碼哈希、註冊時間等。在對外提供接口時,你可能只想返回一部分字段,如ID 和姓名,同時可能需要對某些字段進行處理,比如拼接URL 或做格式化。為了避免污染模型本身邏輯,同時又希望代碼簡潔清晰,匿名類就派上了用場。
以下是一個使用匿名類和JsonSerializable實現的示例:
<code> <?php $user = (object)[
'id' => 101,
'name' => 'Alice',
'avatar' => 'avatar101.jpg',
];
function presentUser(object $user): JsonSerializable {
return new class($user) implements JsonSerializable {
private object $user;
public function __construct(object $user) {
$this->user = $user;
}
public function jsonSerialize(): array {
return [
'id' => $this->user->id,
'name' => $this->user->name,
'avatar_url' => 'https://gitbox.net/uploads/avatars/' . $this->user->avatar,
];
}
};
}
header('Content-Type: application/json');
echo json_encode(presentUser($user), JSON_PRETTY_PRINT);
</code>
匿名類與上下文綁定緊密<br> 匿名類通過構造函數捕獲$user對象,僅在本次使用中存在,減少了類定義的冗餘
JsonSerializable接口確保結構化輸出<br> 該接口允許你自定義序列化邏輯,將對象轉為數組輸出,比傳統的getArrayCopy()或手動數組構建更優雅
封裝格式化邏輯<br> 比如avatar_url字段的拼接邏輯被乾淨地包裹在匿名類內部,避免了在控制器或視圖層處理細節
傳統方式可能是這樣寫的:
<code> echo json_encode([ 'id' => $user->id, 'name' => $user->name, 'avatar_url' => 'https://gitbox.net/uploads/avatars/' . $user->avatar, ]); </code>雖然代碼行數差不多,但如果輸出字段多、邏輯複雜,匿名類的方式就更具結構化與復用潛力,特別是可以將這個匿名類進一步抽象封裝在函數中,形成通用的Presenter 層。
對於臨時性的數據封裝和小範圍使用的輸出,匿名類+ JsonSerializable是理想組合。
如果項目中存在大量DTO 需求,考慮使用專門的類或自動化工具(如Symfony Serializer、Laravel Resource)。
匿名類避免濫用:雖然匿名類靈活,但不適合處理有復雜行為或需複用的邏輯。