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 中, 如何在 controller 或 route 中利用 resource 回傳 resource 的集合, 或是一個有分頁的 response?
<?php

// 可使用 collection method
use App\Http\Resources\User as UserResource;
use App\User;

Route::get('/user', function () {
return UserResource::collection(User::all());
});
在 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 的 resource 當中, 如何移除 data 這個 key? 在AppServiceProvider 加入以下的代碼
<?php

namespace App\Providers;

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

class AppServiceProvider extends ServiceProvider
{
/**
* Register bindings in the container.
*
* @return void
*/
public function register()
{
//
}

/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Resource::withoutWrapping();
}
}
Laravel resource collection 當中, 如果我想要巢狀下的 collection 也有 data key 包住, 該怎麼做? 在 collection 下加入以下程式碼
<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\ResourceCollection;

class CommentsCollection extends ResourceCollection
{
/**
* Transform the resource collection into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return ['data' => $this->collection];
}
}
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,
];
}
Laravel collection 當中, 如果我要有條件的顯示中間表格, 有載入就顯示, 無載入就不顯示, 可以使用哪一個語法? whenPivotLoaded, 第一個 argument 為中間表格, 第二個為 closure
<?php
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'expires_at' => $this->whenPivotLoaded('role_user', function () {
return $this->pivot->expires_at;
}),
];
}
Laravel collection 當中, 如果我想要只在最外層的 meta 中加入客製化的值, 可以怎麼做?
<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\ResourceCollection;

class UserCollection extends ResourceCollection
{
/**
* Transform the resource collection into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return parent::toArray($request);
}

/**
* Get additional data that should be returned with the resource array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function with($request)
{
return [
'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

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

×