Eloquent:序列化
簡介
當使用 Laravel 建構 API 時,您經常需要將您的模型和關聯性轉換為陣列或 JSON。Eloquent 包含了方便的方法來進行這些轉換,以及控制哪些屬性包含在模型的序列化表示中。
為了更穩健地處理 Eloquent 模型和集合的 JSON 序列化,請查看關於 Eloquent API 資源的文件。
序列化模型和集合
序列化為陣列
要將模型及其載入的關聯性轉換為陣列,您應該使用 toArray
方法。這個方法是遞迴的,因此所有屬性和所有關聯(包括關聯的關聯)都將被轉換為陣列
1use App\Models\User;2 3$user = User::with('roles')->first();4 5return $user->toArray();
attributesToArray
方法可用於將模型的屬性轉換為陣列,但不包含其關聯性
1$user = User::first();2 3return $user->attributesToArray();
您也可以通過在集合實例上調用 toArray
方法,將整個模型的集合轉換為陣列
1$users = User::all();2 3return $users->toArray();
序列化為 JSON
要將模型轉換為 JSON,您應該使用 toJson
方法。與 toArray
類似,toJson
方法是遞迴的,因此所有屬性和關聯都將被轉換為 JSON。您還可以指定任何 PHP 支援 的 JSON 編碼選項
1use App\Models\User;2 3$user = User::find(1);4 5return $user->toJson();6 7return $user->toJson(JSON_PRETTY_PRINT);
或者,您可以將模型或集合強制轉換為字串,這將自動在模型或集合上調用 toJson
方法
1return (string) User::find(1);
由於模型和集合在強制轉換為字串時會被轉換為 JSON,您可以直接從應用程式的路由或控制器返回 Eloquent 物件。當 Eloquent 模型和集合從路由或控制器返回時,Laravel 將自動將它們序列化為 JSON
1Route::get('/users', function () {2 return User::all();3});
關聯
當 Eloquent 模型被轉換為 JSON 時,其載入的關聯性將自動作為 JSON 物件上的屬性包含在內。此外,儘管 Eloquent 關聯性方法是使用「駝峰式命名」方法名稱定義的,但關聯性的 JSON 屬性將是「蛇底式命名」。
從 JSON 隱藏屬性
有時您可能希望限制包含在模型陣列或 JSON 表示中的屬性,例如密碼。為此,請將 $hidden
屬性添加到您的模型中。$hidden
屬性陣列中列出的屬性將不會包含在模型的序列化表示中
1<?php 2 3namespace App\Models; 4 5use Illuminate\Database\Eloquent\Model; 6 7class User extends Model 8{ 9 /**10 * The attributes that should be hidden for serialization.11 *12 * @var array<string>13 */14 protected $hidden = ['password'];15}
要隱藏關聯性,請將關聯性的方法名稱添加到 Eloquent 模型的 $hidden
屬性。
或者,您可以使用 visible
屬性來定義應包含在模型陣列和 JSON 表示中的屬性的「允許列表」。當模型轉換為陣列或 JSON 時,所有未在 $visible
陣列中出現的屬性都將被隱藏
1<?php 2 3namespace App\Models; 4 5use Illuminate\Database\Eloquent\Model; 6 7class User extends Model 8{ 9 /**10 * The attributes that should be visible in arrays.11 *12 * @var array13 */14 protected $visible = ['first_name', 'last_name'];15}
暫時修改屬性可見性
如果您想讓給定模型實例上通常隱藏的某些屬性可見,您可以使用 makeVisible
方法。makeVisible
方法返回模型實例
1return $user->makeVisible('attribute')->toArray();
同樣地,如果您想隱藏一些通常可見的屬性,您可以使用 makeHidden
方法。
1return $user->makeHidden('attribute')->toArray();
如果您希望暫時覆蓋所有可見或隱藏的屬性,您可以分別使用 setVisible
和 setHidden
方法
1return $user->setVisible(['id', 'name'])->toArray();2 3return $user->setHidden(['email', 'password', 'remember_token'])->toArray();
將值附加到 JSON
有時,在將模型轉換為陣列或 JSON 時,您可能希望添加在資料庫中沒有相應列的屬性。為此,首先為該值定義一個 accessor
1<?php 2 3namespace App\Models; 4 5use Illuminate\Database\Eloquent\Casts\Attribute; 6use Illuminate\Database\Eloquent\Model; 7 8class User extends Model 9{10 /**11 * Determine if the user is an administrator.12 */13 protected function isAdmin(): Attribute14 {15 return new Attribute(16 get: fn () => 'yes',17 );18 }19}
如果您希望 accessor 始終附加到模型的陣列和 JSON 表示中,您可以將屬性名稱添加到模型的 appends
屬性中。請注意,即使 accessor 的 PHP 方法是使用「駝峰式命名」定義的,屬性名稱通常使用其「蛇底式命名」序列化表示來引用
1<?php 2 3namespace App\Models; 4 5use Illuminate\Database\Eloquent\Model; 6 7class User extends Model 8{ 9 /**10 * The accessors to append to the model's array form.11 *12 * @var array13 */14 protected $appends = ['is_admin'];15}
一旦屬性被添加到 appends
列表,它將被包含在模型的陣列和 JSON 表示中。appends
陣列中的屬性也將遵守模型上設定的 visible
和 hidden
設定。
在運行時附加
在運行時,您可以指示模型實例使用 append
方法附加額外的屬性。或者,您可以使用 setAppends
方法來覆蓋給定模型實例的整個附加屬性陣列
1return $user->append('is_admin')->toArray();2 3return $user->setAppends(['is_admin'])->toArray();
日期序列化
自訂預設日期格式
您可以通過覆蓋 serializeDate
方法來自訂預設序列化格式。此方法不會影響您的日期在資料庫中儲存的格式
1/**2 * Prepare a date for array / JSON serialization.3 */4protected function serializeDate(DateTimeInterface $date): string5{6 return $date->format('Y-m-d');7}
自訂每個屬性的日期格式
您可以通過在模型的 cast 宣告中指定日期格式來自訂個別 Eloquent 日期屬性的序列化格式
1protected function casts(): array2{3 return [4 'birthday' => 'date:Y-m-d',5 'joined_at' => 'datetime:Y-m-d H:00',6 ];7}