Laravel - Eloquent ORM - API Resources

# Introduction

學習一個框架, Ray 的想法是, 在深入理解底層實作的原理之前, 應該先知道這個框架的 使用方法; 先學習怎麼使用這個前人造的輪子, 再學習怎麼樣一個輪子。
所以本篇文章重點在於細讀官方文件, 並將內容理解後以 Q&A 的方式記錄下來, 加速學習以及查詢。



# Generating Resources

在 Laravel 中, 如何使用 CLI 產生一個 resource
php artisan make:resource resourceName
在 Laravel 中, 如何使用 CLI 產生一個 resource collection
  • Answer1:
    php artisan make:resource resourceName --collection
  • Answer2:
    php artisan make:resource resourceNameCollection

# Concept Overview1

在 Laravel 中, Resource 中的 toArray method 的作用是?

將 model 以及自定義的值轉成 array, 然後 Laravel 會自動將 array 轉成 JSON 輸出

在 Laravel 中, 如何在 controller 或 route 中回傳 resource?

直接帶入 closure 回傳

<?php

use App\Http\Resources\User as UserResource;
use App\User;

Route::get('/user', function () {
return new UserResource(User::find(1));
});
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    use App\Http\Resources\User as UserResource;
    use App\User;

    Route::get('/user', function () {
    return UserResource::collection(User::all());
    });
  • Answer:
    使用 UserResource 的 collection method, User models 會依照 UserResource 定義的格式回傳資料, 也可使用 UserCollection
在 Laravel 的 resource 當中, 當我們使用 collection method 時, 是否可回傳額外的 meta data?
不可
在 Laravel 的 resource 當中, 如果我要回傳一個 collection, 或是有分頁的 response, 應該使用?

使用 resource collection

以下的 Laravel example code 的意思是?
  • Example:
    <?php

    namespace App\Http\Resources;

    use Illuminate\Http\Resources\Json\ResourceCollection;

    class UserCollection extends ResourceCollection
    {
    public function toArray($request)
    {
    return [
    'data' => $this->collection,
    'links' => [
    'self' => 'link-value',
    ],
    ];
    }
    }
  • Answer:
    在 resource return 的 collection 中, 在 links array 中新增 ‘self’ => ‘link-value’, 所以 return JSON 如下
    {
    "data": [],
    "links": {
    "first": "http:\/\/example-api.test\/api\/admin\/withdraws?status=11&page=1",
    "last": null,
    "prev": null,
    "next": null,
    "self": "link-value"
    },
    "meta": {
    "current_page": 1,
    "from": null,
    "path": "http:\/\/example-api.test\/api\/admin\/withdraws",
    "per_page": 20,
    "to": null
    }
    }
在 Laravel 的 resource 當中, 如何在 route 或 controller 中利用 resource collection 回傳?
<?php

use App\Http\Resources\UserCollection;
use App\User;

Route::get('/users', function () {
return new UserCollection(User::all());
});
In Laravel 的 Resource 當中, collection 預設會繼承 resource 嗎? 會的

# Customizing The Underlying Resource Class

以下的 Laravel example code 的意思是?
  • Example:
    <?php

    namespace App\Http\Resources;

    use Illuminate\Http\Resources\Json\ResourceCollection;

    class UserCollection extends ResourceCollection
    {
    public $collects = 'App\Http\Resources\Member';
    }
  • Answer:
    指定 UserCollection resource 的來源, 預設是 User Resource


# Writing Resources

Laravel resource 中, 如何帶入 relation?
<?php
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
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,
];
}

# Data Wrapping

以下的 Laravel example code 的意思是?
  • Example:
    <?php

    namespace App\Providers;

    use Illuminate\Http\Resources\Json\Resource;
    use Illuminate\Support\ServiceProvider;

    class AppServiceProvider extends ServiceProvider
    {
    public function register()
    {
    //
    }

    public function boot()
    {
    Resource::withoutWrapping();
    }
    }
  • Answer:
    在 AppServiceProvider, boot() 中使用 withoutWrapping(), 可以移除 Laravel 預設的 Resource response 的 key data
以下的 Laravel example code 的意思是?
  • Example:
    <?php

    namespace App\Http\Resources;

    use Illuminate\Http\Resources\Json\ResourceCollection;

    class CommentsCollection extends ResourceCollection
    {
    public function toArray($request)
    {
    return ['data' => $this->collection];
    }
    }
  • Answer:
    在 Collection class 的 toArray method 中, 使用 [] 在包一層, 修改之後, 底下任何巢狀的資料都會使用 "data" : {} or [] 的方式在包一層
Laravel resource 當中, 如果我要有條件地顯示 secret, 可以用哪一個 clause?
<?php
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'secret' => $this->when(Auth::user()->isAdmin(), 'secret-value'),
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
Laravel 的 resource 當中, 如果我有兩個以上的值想要有條件的顯示, 要就一起顯示, 要就都不顯示, 可以怎麼做?
<?php
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
$this->mergeWhen(Auth::user()->isAdmin(), [
'first-secret' => 'value',
'second-secret' => 'value',
]),
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
Laravel 的 collection 當中, 如果我想要有條件的顯示 relationship, 該 model 有載入 relation 的話我才顯示, 不載入不顯示, 該怎麼做?
<?php
public function toArray($request)
{
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,
];
}
以下位於 Resources 的 Laravel example code 的意思是?
  • Example:
    <?php
    public function toArray($request)
    {
    return [
    'id' => $this->id,
    'name' => $this->name,
    'expires_at' => $this->whenPivotLoaded('role_user', function () {
    return $this->pivot->expires_at;
    }),
    ];
    }
  • Answer:
    當 pivot table 'role_user' 有載入時, 才取得 pivot table 中的 expires_at 值
    若無載入 'role_user', resource 回傳的 'expires_at' 將為 null
以下的 Laravel example code 的意思是?
  • Example:
    <?php

    namespace App\Http\Resources;

    use Illuminate\Http\Resources\Json\ResourceCollection;

    class UserCollection extends ResourceCollection
    {
    public function toArray($request)
    {
    return parent::toArray($request);
    }

    public function with($request)
    {
    return [
    'meta' => [
    'key' => 'value',
    ],
    ];
    }
    }
  • Answer:
    在 meta 中加入自定義的 key / value
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    return (new UserCollection(User::all()->load('roles')))
    ->additional(['meta' => [
    'key' => 'value',
    ]]);
  • Answer:
    在 user resource collection 的 meta array 中, 新增 ‘key’ => ‘value’
Laravel Collection 當中, additional method 的 class是什麼?

Resource

以下的 Laravel example code 的意思是?
  • Example:
    <?php
    use App\Http\Resources\User as UserResource;
    use App\User;

    Route::get('/user', function () {
    return (new UserResource(User::find(1)))
    ->response()
    ->header('X-Value', 'True');
    });
  • Answer:
    以 UserResource 的格式 return, 再利用 response() 指定 header ‘X-Value’ 為 ‘true’
以下的 Laravel example code 的意思是?
  • Example:
    <?php

    namespace App\Http\Resources;

    use Illuminate\Http\Resources\Json\JsonResource;

    class User extends JsonResource
    {
    public function toArray($request)
    {
    return [
    'id' => $this->id,
    ];
    }

    public function withResponse($request, $response)
    {
    $response->header('X-Value', 'True');
    }
    }
  • Answer:
    在 resource file 中使用 withResponse() 來定義 header

# Additional

操作 Resource 的 controller, 通常命名的規則是?

該 Resource 對應的名稱, 如 IpController

以下的 Laravel example code 的意思是?
  • Example:
    <?php
    class EmployeeGenderInfo extends JsonResource
    {
    function __construct(Employee $model)
    {
    parent::__construct($model);
    }
    public function toArray($request)
    {
    return [
    'id' => $this->id,
    'name' => $this->name,
    'gender_name' => $this->gender->name, ];
    }
    }
  • Answer:
    建立一個自定義名稱的 resource, 並指定該 recourse 要使用的 model
Laravel - Getting Started - Configuration Laravel - Getting Started - Deployment

留言

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×