簡介
當建構 API 時,你可能需要一個轉換層,位於 Eloquent Model 和實際回傳給應用程式使用者的 JSON 回應之間。例如,你可能希望為一部分使用者顯示某些屬性而不是其他使用者,或者你可能希望在 Model 的 JSON 表示中始終包含某些關聯。Eloquent 的 Resource 類別讓你可以表達性地且輕鬆地將 Model 和 Model Collection 轉換為 JSON。
當然,你可以使用 Eloquent Model 或 Collection 的 toJson 方法將它們轉換為 JSON;但是,Eloquent Resources 提供了對 Model 及其關聯的 JSON 序列化更細緻和強大的控制。
產生 Resources
要產生一個 Resource 類別,你可以使用 make:resource Artisan 指令。預設情況下,Resources 會放置在應用程式的 app/Http/Resources 目錄中。Resources 繼承 Illuminate\Http\Resources\Json\JsonResource 類別:
php artisan make:resource UserResource
Resource Collections
除了產生轉換個別 Model 的 Resources 之外,你還可以產生負責轉換 Model Collection 的 Resources。這讓你的 JSON 回應可以包含與給定 Resource 整個 Collection 相關的連結和其他元資訊。
要建立一個 Resource Collection,你應該在建立 Resource 時使用 --collection 旗標。或者,在 Resource 名稱中包含 Collection 這個詞會讓 Laravel 知道它應該建立一個 Collection Resource。Collection Resources 繼承 Illuminate\Http\Resources\Json\ResourceCollection 類別:
php artisan make:resource User --collection
php artisan make:resource UserCollection
概念概述
[!NOTE] 這是對 Resources 和 Resource Collections 的高階概述。強烈建議你閱讀本文件的其他章節,以深入了解 Resources 提供給你的自訂和功能。
在深入了解撰寫 Resources 時可用的所有選項之前,讓我們先從高階層面看看如何在 Laravel 中使用 Resources。一個 Resource 類別代表一個需要轉換為 JSON 結構的單一 Model。例如,這是一個簡單的 UserResource Resource 類別:
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class UserResource extends JsonResource
{
/**
* 將 Resource 轉換為陣列。
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
}
每個 Resource 類別都定義一個 toArray 方法,當 Resource 從路由或控制器方法作為回應回傳時,它會回傳應該轉換為 JSON 的屬性陣列。
請注意,我們可以直接從 $this 變數存取 Model 屬性。這是因為 Resource 類別會自動將屬性和方法存取代理到底層 Model 以方便存取。一旦定義了 Resource,它可以從路由或控制器回傳。Resource 透過其建構函式接受底層 Model 實例:
use App\Http\Resources\UserResource;
use App\Models\User;
Route::get('/user/{id}', function (string $id) {
return new UserResource(User::findOrFail($id));
});
為了方便起見,你可以使用 Model 的 toResource 方法,它會使用框架約定自動發現 Model 的底層 Resource:
return User::findOrFail($id)->toResource();
當呼叫 toResource 方法時,Laravel 會嘗試找到一個與 Model 名稱匹配且可選地以 Resource 為後綴的 Resource,位於最接近 Model 命名空間的 Http\Resources 命名空間中。
如果你的 Resource 類別不遵循這個命名約定或位於不同的命名空間,你可以使用 UseResource 屬性為 Model 指定預設的 Resource:
<?php
namespace App\Models;
use App\Http\Resources\CustomUserResource;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Attributes\UseResource;
#[UseResource(CustomUserResource::class)]
class User extends Model
{
// ...
}
或者,你可以透過將它傳遞給 toResource 方法來指定 Resource 類別:
return User::findOrFail($id)->toResource(CustomUserResource::class);
Resource Collections
如果你要回傳一個 Resource Collection 或分頁回應,你應該在路由或控制器中建立 Resource 實例時使用 Resource 類別提供的 collection 方法:
use App\Http\Resources\UserResource;
use App\Models\User;
Route::get('/users', function () {
return UserResource::collection(User::all());
});
或者,為了方便起見,你可以使用 Eloquent Collection 的 toResourceCollection 方法,它會使用框架約定自動發現 Model 的底層 Resource Collection:
return User::all()->toResourceCollection();
當呼叫 toResourceCollection 方法時,Laravel 會嘗試找到一個與 Model 名稱匹配且以 Collection 為後綴的 Resource Collection,位於最接近 Model 命名空間的 Http\Resources 命名空間中。
如果你的 Resource Collection 類別不遵循這個命名約定或位於不同的命名空間,你可以使用 UseResourceCollection 屬性為 Model 指定預設的 Resource Collection:
<?php
namespace App\Models;
use App\Http\Resources\CustomUserCollection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Attributes\UseResourceCollection;
#[UseResourceCollection(CustomUserCollection::class)]
class User extends Model
{
// ...
}
或者,你可以透過將它傳遞給 toResourceCollection 方法來指定 Resource Collection 類別:
return User::all()->toResourceCollection(CustomUserCollection::class);
自訂 Resource Collections
預設情況下,Resource Collections 不允許新增任何可能需要與 Collection 一起回傳的自訂元資料。如果你想自訂 Resource Collection 回應,你可以建立一個專用的 Resource 來代表 Collection:
php artisan make:resource UserCollection
一旦 Resource Collection 類別產生後,你可以輕鬆地定義任何應該包含在回應中的元資料:
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\ResourceCollection;
class UserCollection extends ResourceCollection
{
/**
* 將 Resource Collection 轉換為陣列。
*
* @return array<int|string, mixed>
*/
public function toArray(Request $request): array
{
return [
'data' => $this->collection,
'links' => [
'self' => 'link-value',
],
];
}
}
定義 Resource Collection 後,它可以從路由或控制器回傳:
use App\Http\Resources\UserCollection;
use App\Models\User;
Route::get('/users', function () {
return new UserCollection(User::all());
});
或者,為了方便起見,你可以使用 Eloquent Collection 的 toResourceCollection 方法,它會使用框架約定自動發現 Model 的底層 Resource Collection:
return User::all()->toResourceCollection();
當呼叫 toResourceCollection 方法時,Laravel 會嘗試找到一個與 Model 名稱匹配且以 Collection 為後綴的 Resource Collection,位於最接近 Model 命名空間的 Http\Resources 命名空間中。
保留 Collection 鍵
當從路由回傳 Resource Collection 時,Laravel 會重置 Collection 的鍵,使它們按數字順序排列。但是,你可以在 Resource 類別中新增 preserveKeys 屬性,指示是否應該保留 Collection 的原始鍵:
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class UserResource extends JsonResource
{
/**
* 指示是否應該保留 Resource 的 Collection 鍵。
*
* @var bool
*/
public $preserveKeys = true;
}
當 preserveKeys 屬性設定為 true 時,當 Collection 從路由或控制器回傳時,Collection 鍵將被保留:
use App\Http\Resources\UserResource;
use App\Models\User;
Route::get('/users', function () {
return UserResource::collection(User::all()->keyBy->id);
});
自訂底層 Resource 類別
通常,Resource Collection 的 $this->collection 屬性會自動填入將 Collection 的每個項目映射到其單數 Resource 類別的結果。單數 Resource 類別被假設為 Collection 的類別名稱,去掉類別名稱末尾的 Collection 部分。此外,根據你的個人偏好,單數 Resource 類別可能有也可能沒有 Resource 後綴。
例如,UserCollection 會嘗試將給定的使用者實例映射到 UserResource Resource。要自訂此行為,你可以覆寫 Resource Collection 的 $collects 屬性:
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\ResourceCollection;
class UserCollection extends ResourceCollection
{
/**
* 此 Resource 收集的 Resource。
*
* @var string
*/
public $collects = Member::class;
}
撰寫 Resources
[!NOTE] 如果你還沒有閱讀概念概述,強烈建議你在繼續閱讀本文件之前先閱讀。
Resources 只需要將給定的 Model 轉換為陣列。因此,每個 Resource 都包含一個 toArray 方法,它將你 Model 的屬性轉換為可以從應用程式的路由或控制器回傳的 API 友好陣列:
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class UserResource extends JsonResource
{
/**
* 將 Resource 轉換為陣列。
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
}
一旦定義了 Resource,它可以直接從路由或控制器回傳:
use App\Models\User;
Route::get('/user/{id}', function (string $id) {
return User::findOrFail($id)->toUserResource();
});
關聯
如果你想在回應中包含相關的 Resources,你可以將它們加入到 Resource 的 toArray 方法回傳的陣列中。在這個範例中,我們將使用 PostResource Resource 的 collection 方法將使用者的部落格文章加入到 Resource 回應中:
use App\Http\Resources\PostResource;
use Illuminate\Http\Request;
/**
* 將 Resource 轉換為陣列。
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'posts' => PostResource::collection($this->posts),
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
[!NOTE] 如果你只想在關聯已經載入時才包含它們,請查看條件式關聯的文件。
Resource Collections
雖然 Resources 將單一 Model 轉換為陣列,但 Resource Collections 將 Model Collection 轉換為陣列。但是,並非絕對必要為每個 Model 定義一個 Resource Collection 類別,因為所有 Eloquent Model Collection 都提供 toResourceCollection 方法來動態產生「即時」Resource Collection:
use App\Models\User;
Route::get('/users', function () {
return User::all()->toResourceCollection();
});
但是,如果你需要自訂與 Collection 一起回傳的元資料,則有必要定義你自己的 Resource Collection:
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\ResourceCollection;
class UserCollection extends ResourceCollection
{
/**
* 將 Resource Collection 轉換為陣列。
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'data' => $this->collection,
'links' => [
'self' => 'link-value',
],
];
}
}
與單數 Resources 一樣,Resource Collections 可以直接從路由或控制器回傳:
use App\Http\Resources\UserCollection;
use App\Models\User;
Route::get('/users', function () {
return new UserCollection(User::all());
});
或者,為了方便起見,你可以使用 Eloquent Collection 的 toResourceCollection 方法,它會使用框架約定自動發現 Model 的底層 Resource Collection:
return User::all()->toResourceCollection();
當呼叫 toResourceCollection 方法時,Laravel 會嘗試找到一個與 Model 名稱匹配且以 Collection 為後綴的 Resource Collection,位於最接近 Model 命名空間的 Http\Resources 命名空間中。
資料包裝
預設情況下,當 Resource 回應轉換為 JSON 時,最外層的 Resource 會被包裝在 data 鍵中。因此,例如,一個典型的 Resource Collection 回應看起來像這樣:
{
"data": [
{
"id": 1,
"name": "Eladio Schroeder Sr.",
"email": "therese28@example.com"
},
{
"id": 2,
"name": "Liliana Mayert",
"email": "evandervort@example.com"
}
]
}
如果你想停用最外層 Resource 的包裝,你應該在基礎 Illuminate\Http\Resources\Json\JsonResource 類別上呼叫 withoutWrapping 方法。通常,你應該從 AppServiceProvider 或另一個在每次請求時載入的服務提供者呼叫此方法:
<?php
namespace App\Providers;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* 註冊任何應用程式服務。
*/
public function register(): void
{
// ...
}
/**
* 啟動任何應用程式服務。
*/
public function boot(): void
{
JsonResource::withoutWrapping();
}
}
[!WARNING] >
withoutWrapping方法只影響最外層的回應,不會移除你手動加入到自己 Resource Collections 的data鍵。
包裝巢狀 Resources
你可以完全自由地決定 Resource 的關聯如何被包裝。如果你希望所有 Resource Collections 都被包裝在 data 鍵中,無論它們的巢狀層級如何,你應該為每個 Resource 定義一個 Resource Collection 類別,並在 data 鍵中回傳 Collection。
你可能會想知道這是否會導致最外層的 Resource 被包裝在兩個 data 鍵中。別擔心,Laravel 永遠不會讓你的 Resources 意外地被雙重包裝,所以你不必擔心正在轉換的 Resource Collection 的巢狀層級:
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\ResourceCollection;
class CommentsCollection extends ResourceCollection
{
/**
* 將 Resource Collection 轉換為陣列。
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return ['data' => $this->collection];
}
}
資料包裝與分頁
當透過 Resource 回應回傳分頁 Collections 時,即使呼叫了 withoutWrapping 方法,Laravel 也會將 Resource 資料包裝在 data 鍵中。這是因為分頁回應總是包含關於分頁器狀態的 meta 和 links 鍵:
{
"data": [
{
"id": 1,
"name": "Eladio Schroeder Sr.",
"email": "therese28@example.com"
},
{
"id": 2,
"name": "Liliana Mayert",
"email": "evandervort@example.com"
}
],
"links": {
"first": "http://example.com/users?page=1",
"last": "http://example.com/users?page=1",
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"path": "http://example.com/users",
"per_page": 15,
"to": 10,
"total": 10
}
}
分頁
你可以將 Laravel 分頁器實例傳遞給 Resource 的 collection 方法或自訂 Resource Collection:
use App\Http\Resources\UserCollection;
use App\Models\User;
Route::get('/users', function () {
return new UserCollection(User::paginate());
});
或者,為了方便起見,你可以使用分頁器的 toResourceCollection 方法,它會使用框架約定自動發現分頁 Model 的底層 Resource Collection:
return User::paginate()->toResourceCollection();
分頁回應總是包含關於分頁器狀態的 meta 和 links 鍵:
{
"data": [
{
"id": 1,
"name": "Eladio Schroeder Sr.",
"email": "therese28@example.com"
},
{
"id": 2,
"name": "Liliana Mayert",
"email": "evandervort@example.com"
}
],
"links": {
"first": "http://example.com/users?page=1",
"last": "http://example.com/users?page=1",
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"path": "http://example.com/users",
"per_page": 15,
"to": 10,
"total": 10
}
}
自訂分頁資訊
如果你想自訂分頁回應中 links 或 meta 鍵中包含的資訊,你可以在 Resource 上定義一個 paginationInformation 方法。此方法會接收 $paginated 資料和 $default 資訊陣列,這是一個包含 links 和 meta 鍵的陣列:
/**
* 自訂 Resource 的分頁資訊。
*
* @param \Illuminate\Http\Request $request
* @param array $paginated
* @param array $default
* @return array
*/
public function paginationInformation($request, $paginated, $default)
{
$default['links']['custom'] = 'https://example.com';
return $default;
}
條件式屬性
有時你可能希望只在滿足給定條件時才在 Resource 回應中包含屬性。例如,你可能希望只在當前使用者是「管理員」時才包含一個值。Laravel 提供了各種輔助方法來協助你處理這種情況。when 方法可用於有條件地將屬性加入到 Resource 回應中:
/**
* 將 Resource 轉換為陣列。
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'secret' => $this->when($request->user()->isAdmin(), 'secret-value'),
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
在這個範例中,只有當已認證使用者的 isAdmin 方法回傳 true 時,secret 鍵才會在最終 Resource 回應中回傳。如果該方法回傳 false,secret 鍵會在 Resource 回應發送給客戶端之前被移除。when 方法讓你可以表達性地定義 Resources,而無需在建構陣列時使用條件陳述式。
when 方法也接受閉包作為其第二個參數,讓你只在給定條件為 true 時才計算結果值:
'secret' => $this->when($request->user()->isAdmin(), function () {
return 'secret-value';
}),
whenHas 方法可用於在屬性實際存在於底層 Model 時包含它:
'name' => $this->whenHas('name'),
此外,whenNotNull 方法可用於在屬性不為 null 時將它包含在 Resource 回應中:
'name' => $this->whenNotNull($this->name),
合併條件式屬性
有時你可能有多個屬性應該只在相同條件下包含在 Resource 回應中。在這種情況下,你可以使用 mergeWhen 方法,只在給定條件為 true 時才將屬性包含在回應中:
/**
* 將 Resource 轉換為陣列。
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
$this->mergeWhen($request->user()->isAdmin(), [
'first-secret' => 'value',
'second-secret' => 'value',
]),
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
同樣地,如果給定條件為 false,這些屬性會在 Resource 回應發送給客戶端之前被移除。
[!WARNING] >
mergeWhen方法不應該用於混合字串和數字鍵的陣列中。此外,它不應該用於數字鍵未按順序排列的陣列中。
條件式關聯
除了有條件地載入屬性之外,你還可以根據關聯是否已經載入到 Model 上,有條件地在 Resource 回應中包含關聯。這讓你的控制器可以決定哪些關聯應該載入到 Model 上,而 Resource 可以在它們實際被載入時才輕鬆地包含它們。最終,這讓你更容易避免 Resources 中的「N+1」查詢問題。
whenLoaded 方法可用於有條件地載入關聯。為了避免不必要地載入關聯,此方法接受關聯的名稱而不是關聯本身:
use App\Http\Resources\PostResource;
/**
* 將 Resource 轉換為陣列。
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'posts' => PostResource::collection($this->whenLoaded('posts')),
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
在這個範例中,如果關聯尚未載入,posts 鍵會在 Resource 回應發送給客戶端之前被移除。
條件式關聯計數
除了有條件地包含關聯之外,你還可以根據關聯的計數是否已載入到 Model 上,有條件地在 Resource 回應中包含關聯「計數」:
new UserResource($user->loadCount('posts'));
whenCounted 方法可用於有條件地在 Resource 回應中包含關聯的計數。如果關聯的計數不存在,此方法會避免不必要地包含屬性:
/**
* 將 Resource 轉換為陣列。
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'posts_count' => $this->whenCounted('posts'),
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
在這個範例中,如果 posts 關聯的計數尚未載入,posts_count 鍵會在 Resource 回應發送給客戶端之前被移除。
其他類型的聚合,如 avg、sum、min 和 max,也可以使用 whenAggregated 方法有條件地載入:
'words_avg' => $this->whenAggregated('posts', 'words', 'avg'),
'words_sum' => $this->whenAggregated('posts', 'words', 'sum'),
'words_min' => $this->whenAggregated('posts', 'words', 'min'),
'words_max' => $this->whenAggregated('posts', 'words', 'max'),
條件式 Pivot 資訊
除了有條件地在 Resource 回應中包含關聯資訊之外,你還可以使用 whenPivotLoaded 方法有條件地包含多對多關聯的中間資料表的資料。whenPivotLoaded 方法接受 pivot 資料表的名稱作為其第一個參數。第二個參數應該是一個閉包,它回傳當 Model 上有 pivot 資訊時要回傳的值:
/**
* 將 Resource 轉換為陣列。
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'expires_at' => $this->whenPivotLoaded('role_user', function () {
return $this->pivot->expires_at;
}),
];
}
如果你的關聯使用自訂中間資料表 Model,你可以將中間資料表 Model 的實例作為第一個參數傳遞給 whenPivotLoaded 方法:
'expires_at' => $this->whenPivotLoaded(new Membership, function () {
return $this->pivot->expires_at;
}),
如果你的中間資料表使用的存取器不是 pivot,你可以使用 whenPivotLoadedAs 方法:
/**
* 將 Resource 轉換為陣列。
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'expires_at' => $this->whenPivotLoadedAs('subscription', 'role_user', function () {
return $this->subscription->expires_at;
}),
];
}
新增元資料
一些 JSON API 標準要求在 Resource 和 Resource Collection 回應中新增元資料。這通常包括 Resource 或相關 Resources 的 links,或關於 Resource 本身的元資料。如果你需要回傳關於 Resource 的額外元資料,請將其包含在你的 toArray 方法中。例如,你可能在轉換 Resource Collection 時包含 links 資訊:
/**
* 將 Resource 轉換為陣列。
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'data' => $this->collection,
'links' => [
'self' => 'link-value',
],
];
}
當從 Resources 回傳額外的元資料時,你永遠不必擔心意外覆蓋 Laravel 在回傳分頁回應時自動新增的 links 或 meta 鍵。你定義的任何額外 links 都會與分頁器提供的連結合併。
頂層元資料
有時你可能希望只在 Resource 是正在回傳的最外層 Resource 時才包含某些元資料。通常,這包括關於整個回應的元資訊。要定義此元資料,請在 Resource 類別中新增一個 with 方法。此方法應該回傳一個元資料陣列,只有當 Resource 是正在轉換的最外層 Resource 時才會包含在 Resource 回應中:
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\ResourceCollection;
class UserCollection extends ResourceCollection
{
/**
* 將 Resource Collection 轉換為陣列。
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return parent::toArray($request);
}
/**
* 取得應該與 Resource 陣列一起回傳的額外資料。
*
* @return array<string, mixed>
*/
public function with(Request $request): array
{
return [
'meta' => [
'key' => 'value',
],
];
}
}
在建構 Resources 時新增元資料
你也可以在路由或控制器中建構 Resource 實例時新增頂層資料。所有 Resources 都有 additional 方法,它接受一個應該新增到 Resource 回應的資料陣列:
return User::all()
->load('roles')
->toResourceCollection()
->additional(['meta' => [
'key' => 'value',
]]);
Resource 回應
如你所讀,Resources 可以直接從路由和控制器回傳:
use App\Models\User;
Route::get('/user/{id}', function (string $id) {
return User::findOrFail($id)->toResource();
});
但是,有時你可能需要在將傳出的 HTTP 回應發送給客戶端之前自訂它。有兩種方式可以完成這個操作。首先,你可以在 Resource 上鏈接 response 方法。此方法會回傳一個 Illuminate\Http\JsonResponse 實例,讓你完全控制回應的標頭:
use App\Http\Resources\UserResource;
use App\Models\User;
Route::get('/user', function () {
return User::find(1)
->toResource()
->response()
->header('X-Value', 'True');
});
或者,你可以在 Resource 本身中定義一個 withResponse 方法。當 Resource 作為回應中最外層的 Resource 回傳時,會呼叫此方法:
<?php
namespace App\Http\Resources;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class UserResource extends JsonResource
{
/**
* 將 Resource 轉換為陣列。
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
];
}
/**
* 自訂 Resource 的傳出回應。
*/
public function withResponse(Request $request, JsonResponse $response): void
{
$response->header('X-Value', 'True');
}
}