Khi chúng ta muốn custom dữ liệu trả về của api, chúng ta sẽ sử dụng laravel resource, hoặc sử dụng packgist bên thứ 3 như Dingo API. Hôm nay chúng ta sẽ tìm hiểu Laravel resource
để transform dữ liệu trả về của api.
Tạo resource api với command, các files resource được tạo trong folder app/Http/Resources
php artisan make:resource UserResource
// Create resource collection
php artisan make:resource User --collection
php artisan make:resource UserCollection
Tạo 1 file BaseResource đinh nghĩa response trả về cho api
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class BaseResource extends JsonResource
{
/**
* @var string
*/
public $msg;
public function __construct($resource = null, $msg = 'success')
{
parent::__construct($resource);
$this->msg = $msg;
}
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/
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 [
'status' => true,
'message' => $this->msg,
];
}
}
Tạo UserResource để transform dữ liệu trả về cho api detail user.
<?php
namespace App\Http\Resources\Users;
use App\Http\Resources\BaseResource;
class UserResource extends BaseResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/
public function toArray($request)
{
return [
'name' => $this->name,
'email' => $this->email,
];
}
}
Tạo api get detail user
<?php
namespace App\Http\Controllers\Api\V1;
use App\Http\Controllers\Controller;
use App\Http\Requests\Users\UpdateUserRequest;
use App\Http\Resources\PaginationResource;
use App\Http\Resources\SuccessResource;
use App\Http\Resources\Users\UserResource;
use App\Http\Resources\Users\UsersResource;
use App\Models\User;
class UserController extends Controller
{
/**
* Detail user
*
* @OA\Get(
* path="/api/v1/users/{userId}",
* tags={"Users"},
* security={ {"sanctum" : {} }},
* @OA\Parameter(ref="#/components/parameters/userId"),
* @OA\Response(
* response=200,
* description="Successful operation",
* @OA\JsonContent(ref="#/components/schemas/UserResource")
* ),
* )
* @param int $id
* @return UserResource
*/
public function show(int $id): UserResource
{
$user = User::find($id);
return new UserResource($user);
}
}
Response api get detail đã được transfrom và trả về theo format sau
{
"data": {
"name": "huunv",
"email": "huunv@gmail.com"
},
"status": true,
"message": "success"
}
Tạo collection resource để định nghĩa response chung trả về
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\ResourceCollection;
class CollectionResource extends ResourceCollection
{
/**
* @var string
*/
public $msg;
public function __construct($resource = null, $msg = 'success')
{
parent::__construct($resource);
$this->msg = $msg;
}
/**
* Transform the resource collection into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'data' => $this->collection,
];
}
/**
* Get additional data that should be returned with the resource array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function with($request)
{
return [
'status' => true,
'message' => $this->msg,
];
}
}
Tạo UsersResource
trả về response với data trả về là 1 collection.
<?php
namespace App\Http\Resources\Users;
use App\Http\Resources\CollectionResource;
use App\Http\Resources\Users\UserResource;
class UsersResource extends CollectionResource
{
/**
* Transform the resource collection into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
// Transform data by UserResource
//'data' => UserResource::collection($this->collection),
// Get all data in collection
//'data' => $this->collection,
// Custom transfrom data
'data' => $this->collection->transform(function($user) {
return [
'id' => $user->id,
'title' => $user->name,
'slug' => $user->email,
];
}),
];
}
}
Controller trả về resource collection
<?php
namespace App\Http\Controllers\Api\V1;
use App\Http\Controllers\Controller;
use App\Http\Resources\Users\UsersResource;
use App\Models\User;
class UserController extends Controller
{
/**
* List users
*
* @OA\Get(
* path="/api/v1/users",
* tags={"Users"},
* security={ {"sanctum" : {} }},
* @OA\Response(
* response=200,
* description="Successful operation",
* @OA\JsonContent(ref="#/components/schemas/UsersResource")
* ),
* @OA\Response(
* response=401,
* description="Unauthenticated",
* ),
* @OA\Response(
* response=403,
* description="Forbidden"
* )
* )
*/
public function index()
{
$user = User::orderByDesc('id')->get();
return new UsersResource($user);
}
}
Response trả về cho api get list users
{
"data": [
{
"id": 2,
"name": "huunv2",
"email": "huunv2@gmail.com"
},
{
"id": 1,
"name": "huunv",
"email": "huunv@gmail.com"
}
],
"success": true,
"message": "success"
}
Tạo file PagintionResource
transform data dạng phân trang
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\ResourceCollection;
class PaginationResource extends ResourceCollection
{
/**
* @var array
*/
protected $pagination;
protected $msg;
public function __construct($resource, $msg = 'success')
{
$this->pagination = [
'total' => $resource->total(),
'per_page' => $resource->perPage(),
'current_page' => $resource->currentPage(),
'last_page' => $resource->lastPage(),
'total_page' => ceil($resource->total() / $resource->perPage()),
];
$this->msg = $msg;
$resource = $resource->getCollection();
parent::__construct($resource);
}
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/
public function toArray($request)
{
return [
'data' => $this->collection,
'pagination' => $this->pagination,
'status' => true,
'message' => $this->msg,
];
}
}
Tạo UsersPaginationResource
để transform data dang pagination.
<?php
namespace App\Http\Resources\Users;
use App\Http\Resources\PaginationResource;
use App\Http\Resources\Users\UserResource;
class UsersPaginationResource extends PaginationResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/
public function toArray($request)
{
return [
'data' => UserResource::collection($this->collection),
'pagination' => $this->pagination,
'status' => true,
'message' => $this->msg,
];
}
}
Tạo controller trả về UsersPaginationResource
<?php
namespace App\Http\Controllers\Api\V1;
use App\Http\Controllers\Controller;
use App\Http\Resources\Users\UsersPaginationResource;
class UserController extends Controller
{
/**
* List users
*
* @OA\Get(
* path="/api/v1/users",
* tags={"Users"},
* security={ {"sanctum" : {} }},
* @OA\Response(
* response=200,
* description="Successful operation",
* @OA\JsonContent(ref="#/components/schemas/UsersResource")
* ),
* @OA\Response(
* response=401,
* description="Unauthenticated",
* ),
* @OA\Response(
* response=403,
* description="Forbidden"
* )
* )
*/
public function index()
{
$users = User::paginate(2);
return new UsersPaginationResource($users);
}
}
Response của api trả về với dạng pagination
{
"data": [
{
"id": 1,
"name": "huunv",
"email": "huunv@gmail.com"
},
{
"id": 2,
"name": "huunv2",
"email": "huunv2@gmail.com"
}
],
"pagination": {
"total": 2,
"per_page": 2,
"current_page": 1,
"last_page": 1,
"total_page": 1
},
"status": true,
"message": "success"
}
Tạo file SuccessResource
trả về response trường hợp không cần trả về data, như api xoá user.
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
/**
* @OA\Schema(
* properties={
* @OA\Property(
* property="success",
* type="bool",
* example="true"
* ),
* @OA\Property(
* property="data",
* example=null,
* ),
* @OA\Property(
* property="message",
* type="string",
* example="success"
* )
* }
* )
*/
class SuccessResource extends JsonResource
{
/**
* @var string
*/
public $msg;
public function __construct($msg = 'success')
{
$this->msg = $msg;
}
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/
public function toArray($request)
{
self::withoutWrapping();
return [
'data' => null,
'status' => true,
'message' => $this->msg,
];
}
}
Tạo api delete user trả về SuccessResource
<?php
namespace App\Http\Controllers\Api\V1;
use App\Http\Controllers\Controller;
use App\Http\Resources\SuccessResource;
class UserController extends Controller
{
/**
* Delete user
*
* @OA\Delete(
* path="/api/v1/users/{userId}",
* tags={"Users"},
* security={ {"sanctum" : {} }},
* @OA\Parameter(ref="#/components/parameters/userId"),
* @OA\Response(
* response=200,
* description="Successful operation",
* @OA\JsonContent(ref="#/components/schemas/SuccessResource")
* ),
* )
* @param int $id
* @return SuccessResource
*/
public function destroy(int $id): SuccessResource
{
User::where(['id' => $id])->delete();
return new SuccessResource('Delete success');
}
}
Response api trả về
{
"data": null,
"status": true,
"message": "Delete success"
}
Như Vậy là chúng ta đã transform dữ liệu thành công khi sử dụng resource api, giúp cho ứng dụng của bạn trở lên cực kì mạnh mẽ rồi đó. Thanks for reading...