TechTopia Casing SSD NVMe NGFF USB 3.1 Type-C Enclosure Eksternal M.2 SATA & NVMe High Speed

Laravel API Resource: Cara Membuat Response JSON yang Konsisten

Membuat REST API dengan Laravel bukan hanya tentang mengambil data dari database dan mengembalikannya dalam format JSON. Ketika aplikasi mulai berkembang, struktur response yang tidak konsisten dapat menyulitkan frontend, aplikasi mobile, maupun layanan lain yang menggunakan API.

Laravel menyediakan API Resource untuk membantu mengontrol dan membentuk response JSON secara lebih terstruktur. Dengan API Resource, developer dapat menentukan field apa saja yang dikirim ke client, mengubah nama field, menambahkan informasi tambahan, serta menjaga format response tetap konsisten.

Pada tutorial ini, kita akan membahas Laravel API Resource dari dasar, mulai dari membuat resource, menggunakannya pada controller, collection, pagination, relationship, conditional field, hingga membuat response API yang lebih rapi.

Apa Itu Laravel API Resource?

Laravel API Resource adalah layer transformasi yang digunakan untuk mengubah model atau collection Eloquent menjadi struktur JSON yang sesuai dengan kebutuhan API.

Tanpa API Resource, controller mungkin langsung mengembalikan model:

return response()->json($post);

Cara tersebut memang sederhana, tetapi seluruh atribut model yang terlihat dapat ikut menjadi bagian dari response.

Dengan API Resource:

return new PostResource($post);

Developer dapat menentukan secara eksplisit data apa yang ingin diberikan kepada client.

Secara sederhana, API Resource berada di antara model dan response API:

Database
    ↓
Eloquent Model
    ↓
API Resource
    ↓
JSON Response
    ↓
Frontend / Mobile / Client

Pendekatan ini membuat struktur response tidak terlalu bergantung pada struktur internal database.

Mengapa API Resource Penting?

Pada project kecil, mengembalikan model secara langsung mungkin terasa praktis. Namun, pada aplikasi yang lebih besar, pendekatan tersebut dapat menimbulkan beberapa masalah.

Misalnya model User memiliki field:

id
name
email
password
remember_token
created_at
updated_at

Tidak semua field tersebut seharusnya dikirim ke client.

API Resource memungkinkan kita memilih field secara eksplisit:

{
    "id": 1,
    "name": "Budi",
    "email": "[email protected]"
}

Selain keamanan, API Resource juga membantu ketika format database berubah tetapi kontrak API harus tetap stabil.

Membuat Model dan Migration

Untuk contoh, kita akan menggunakan model Post.

Jika model belum tersedia:

php artisan make:model Post -m

Pada migration, buat struktur sederhana:

Schema::create('posts', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->text('content');
    $table->timestamps();
});

Kemudian jalankan:

php artisan migrate

Membuat API Resource

Laravel menyediakan Artisan command untuk membuat API Resource:

php artisan make:resource PostResource

File resource akan dibuat di:

app/Http/Resources/PostResource.php

Struktur awalnya kurang lebih seperti:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class PostResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     */
    public function toArray(Request $request): array
    {
        return parent::toArray($request);
    }
}

Method toArray() merupakan bagian utama dari API Resource.

Di sinilah kita menentukan struktur JSON yang akan dikirim kepada client.

Membuat Response JSON Sederhana

Ubah PostResource menjadi:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class PostResource extends JsonResource
{
    public function toArray(Request $request): array
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'content' => $this->content,
            'created_at' => $this->created_at,
        ];
    }
}

Sekarang response tidak lagi mengikuti seluruh atribut model secara otomatis.

Kita menentukan sendiri field yang boleh ditampilkan.

Menggunakan Resource di Controller

Misalnya kita memiliki controller:

php artisan make:controller Api/PostController --api

Import resource:

use App\Http\Resources\PostResource;
use App\Models\Post;

Kemudian method show() dapat dibuat:

public function show(Post $post)
{
    return new PostResource($post);
}

Ketika endpoint:

GET /api/posts/1

dipanggil, response akan berasal dari struktur yang kita definisikan di PostResource.

Contoh:

{
    "data": {
        "id": 1,
        "title": "Belajar Laravel API",
        "content": "Membuat REST API dengan Laravel.",
        "created_at": "2026-08-28T10:00:00.000000Z"
    }
}

Laravel Resource secara default membungkus resource tunggal dalam key data.

Menghilangkan Wrapper data

Dalam beberapa desain API, Anda mungkin ingin response langsung berada di root JSON.

Untuk menghilangkan wrapper tersebut, Anda dapat mengatur konfigurasi resource:

public static $wrap = null;

Contoh:

class PostResource extends JsonResource
{
    public static $wrap = null;

    public function toArray(Request $request): array
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'content' => $this->content,
        ];
    }
}

Response kemudian menjadi:

{
    "id": 1,
    "title": "Belajar Laravel API",
    "content": "Membuat REST API dengan Laravel."
}

Namun, penggunaan wrapper data juga merupakan pola yang umum. Yang paling penting adalah memilih satu format dan menggunakannya secara konsisten.

Membuat Resource Collection

Untuk mengembalikan banyak data, kita dapat menggunakan PostResource::collection().

Contohnya:

public function index()
{
    $posts = Post::latest()->get();

    return PostResource::collection($posts);
}

Response:

{
    "data": [
        {
            "id": 1,
            "title": "Post Pertama",
            "content": "Isi post pertama."
        },
        {
            "id": 2,
            "title": "Post Kedua",
            "content": "Isi post kedua."
        }
    ]
}

Dengan demikian, resource tunggal dan collection memiliki struktur yang konsisten.

Menggunakan API Resource dengan Pagination

Pada aplikasi production, hindari mengambil seluruh data sekaligus jika jumlah record dapat bertambah besar.

Gunakan pagination:

public function index()
{
    $posts = Post::latest()->paginate(10);

    return PostResource::collection($posts);
}

Laravel akan menyertakan informasi pagination pada response.

Contohnya:

{
    "data": [
        {
            "id": 1,
            "title": "Post Pertama",
            "content": "Isi post pertama."
        }
    ],
    "links": {
        "first": "http://example.test/api/posts?page=1",
        "last": "http://example.test/api/posts?page=5",
        "prev": null,
        "next": "http://example.test/api/posts?page=2"
    },
    "meta": {
        "current_page": 1,
        "last_page": 5,
        "per_page": 10,
        "total": 50
    }
}

Frontend dapat menggunakan metadata tersebut untuk membuat pagination.

Mengubah Nama Field

API Resource juga berguna ketika nama field database tidak sesuai dengan format yang ingin digunakan API.

Misalnya database memiliki:

created_at
updated_at

API dapat menggunakan nama:

createdAt
updatedAt

Resource:

return [
    'id' => $this->id,
    'title' => $this->title,
    'createdAt' => $this->created_at,
    'updatedAt' => $this->updated_at,
];

Dengan begitu, struktur internal database tidak harus sama dengan kontrak API.

Mengubah Format Tanggal

Resource juga dapat digunakan untuk menentukan format tanggal.

Contohnya:

'created_at' => $this->created_at?->format('Y-m-d H:i:s'),

Response:

{
    "id": 1,
    "title": "Belajar Laravel",
    "created_at": "2026-08-28 10:30:00"
}

Format tanggal sebaiknya ditentukan secara konsisten agar client tidak perlu menebak format yang digunakan.

Untuk API lintas zona waktu, pertimbangkan penggunaan format ISO 8601 dan pastikan aturan timezone aplikasi sudah jelas.

Menambahkan Field Turunan

API Resource dapat menghasilkan field yang tidak secara langsung tersimpan di database.

Misalnya kita ingin menambahkan excerpt:

return [
    'id' => $this->id,
    'title' => $this->title,
    'excerpt' => str($this->content)->limit(100),
];

Response:

{
    "id": 1,
    "title": "Belajar Laravel API",
    "excerpt": "Laravel menyediakan berbagai fitur untuk membangun..."
}

Dengan cara ini, client tidak perlu melakukan transformasi sederhana sendiri.

Menggunakan Accessor dari Model

Jika model memiliki accessor, API Resource juga dapat menggunakannya.

Misalnya model memiliki attribute:

protected function fullName(): Attribute
{
    return Attribute::make(
        get: fn () => "{$this->first_name} {$this->last_name}",
    );
}

Resource dapat menggunakannya:

return [
    'id' => $this->id,
    'name' => $this->full_name,
];

Ini memungkinkan response API menggunakan representasi data yang lebih nyaman untuk client.

Menampilkan Relationship

Misalnya setiap post memiliki user.

Pada model Post:

public function user()
{
    return $this->belongsTo(User::class);
}

Buat resource untuk user:

php artisan make:resource UserResource

Kemudian:

public function toArray(Request $request): array
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'email' => $this->email,
    ];
}

Pada PostResource:

use App\Http\Resources\UserResource;

Kemudian:

return [
    'id' => $this->id,
    'title' => $this->title,
    'content' => $this->content,
    'author' => new UserResource($this->whenLoaded('user')),
];

Di controller, eager load relationship:

public function show(Post $post)
{
    $post->load('user');

    return new PostResource($post);
}

Response dapat menjadi:

{
    "data": {
        "id": 1,
        "title": "Belajar Laravel API",
        "content": "Membuat REST API dengan Laravel.",
        "author": {
            "id": 1,
            "name": "Budi",
            "email": "[email protected]"
        }
    }
}

Menggunakan whenLoaded()

Penggunaan whenLoaded() penting ketika relationship tidak selalu dibutuhkan.

Contoh:

'author' => new UserResource($this->whenLoaded('user')),

Dengan pendekatan ini, relationship hanya ditampilkan ketika memang sudah dimuat.

Hal tersebut membantu mencegah query tambahan yang tidak diperlukan.

Menghindari N+1 Query

Relationship yang digunakan dalam API Resource sebaiknya dipersiapkan menggunakan eager loading.

Contoh:

$posts = Post::with('user')
    ->latest()
    ->get();

return PostResource::collection($posts);

Daripada membiarkan setiap item melakukan query user secara terpisah, relationship sudah dimuat dalam query yang sesuai.

Untuk data dalam jumlah besar, perhatian terhadap query seperti ini sangat penting karena masalah N+1 dapat berdampak pada performa API.

Conditional Attribute

API Resource dapat menampilkan field hanya jika kondisi tertentu terpenuhi.

Contohnya:

'email' => $this->when(
    $request->user()?->isAdmin(),
    $this->email
),

Dengan cara tersebut, email hanya dikirim kepada user yang memenuhi kondisi tertentu.

Namun, jangan hanya mengandalkan Resource untuk authorization. Hak akses tetap sebaiknya ditentukan menggunakan policy, gate, atau mekanisme authorization yang sesuai.

Conditional Relationship

Relationship juga dapat ditampilkan berdasarkan kondisi:

'comments' => CommentResource::collection(
    $this->whenLoaded('comments')
),

Jika relationship comments tidak dimuat, field tersebut tidak perlu dipaksakan untuk muncul.

Menambahkan Meta Data

Kadang API membutuhkan metadata tambahan di luar resource utama.

Laravel memungkinkan response resource memiliki metadata tambahan.

Contoh:

return (new PostResource($post))
    ->additional([
        'meta' => [
            'version' => '1.0',
        ],
    ]);

Response:

{
    "data": {
        "id": 1,
        "title": "Belajar Laravel API"
    },
    "meta": {
        "version": "1.0"
    }
}

Metadata dapat digunakan untuk informasi tambahan yang relevan dengan response API.

Menambahkan Link

Resource juga dapat menyertakan link.

Contoh:

return [
    'id' => $this->id,
    'title' => $this->title,
    'links' => [
        'self' => route('posts.show', $this->id),
    ],
];

Response:

{
    "data": {
        "id": 1,
        "title": "Belajar Laravel API",
        "links": {
            "self": "http://example.test/api/posts/1"
        }
    }
}

Link dapat membantu client menemukan endpoint terkait tanpa harus mengetahui seluruh URL secara manual.

Membuat Response Success yang Konsisten

API Resource sebaiknya menjadi bagian dari pola response yang konsisten.

Misalnya seluruh response resource menggunakan:

{
    "data": {}
}

Sedangkan metadata menggunakan:

{
    "data": {},
    "meta": {}
}

Untuk collection:

{
    "data": []
}

Dengan pola tersebut, frontend dapat memiliki ekspektasi yang jelas terhadap struktur response.

Response Error Tetap Perlu Dirancang

API Resource tidak menangani seluruh aspek desain response API.

Error response juga perlu memiliki format yang konsisten.

Contoh:

{
    "message": "Data tidak ditemukan.",
    "errors": {
        "post": [
            "Post yang diminta tidak tersedia."
        ]
    }
}

Untuk validation error, Laravel sudah menyediakan mekanisme response yang dapat digunakan dan disesuaikan dengan kebutuhan aplikasi.

Yang penting adalah menjaga format error agar mudah diproses oleh client.

API Resource untuk Create dan Update

API Resource umumnya digunakan untuk mengubah output, bukan untuk memproses input request.

Misalnya ketika membuat post:

public function store(Request $request)
{
    $validated = $request->validate([
        'title' => ['required', 'string', 'max:255'],
        'content' => ['required', 'string'],
    ]);

    $post = Post::create($validated);

    return new PostResource($post);
}

Validasi tetap dilakukan melalui request validation atau Form Request.

Resource bertugas membentuk response setelah data berhasil diproses.

Menggunakan Form Request Bersama Resource

Untuk controller yang lebih rapi, validasi dapat dipindahkan ke Form Request.

Buat:

php artisan make:request StorePostRequest

Kemudian controller:

public function store(StorePostRequest $request)
{
    $post = Post::create($request->validated());

    return new PostResource($post);
}

Dengan pendekatan tersebut, tanggung jawab setiap komponen menjadi lebih jelas:

Form Request
    ↓
Validasi Input

Controller
    ↓
Business Flow

Model
    ↓
Data & Database

API Resource
    ↓
Transformasi Output

Membuat Resource Collection dengan Response Tambahan

Kita juga dapat memberikan metadata pada collection:

return PostResource::collection($posts)
    ->additional([
        'meta' => [
            'version' => '1.0',
        ],
    ]);

Response:

{
    "data": [
        {
            "id": 1,
            "title": "Post Pertama"
        }
    ],
    "meta": {
        "version": "1.0"
    }
}

Ini dapat digunakan untuk informasi seperti versi API, konteks response, atau metadata lain yang relevan.

Struktur Project

Setelah menggunakan API Resource, struktur project dapat menjadi:

app/
├── Http/
│   ├── Controllers/
│   │   └── Api/
│   │       └── PostController.php
│   ├── Requests/
│   │   └── StorePostRequest.php
│   └── Resources/
│       ├── PostResource.php
│       └── UserResource.php
└── Models/
    ├── Post.php
    └── User.php

Struktur ini membantu memisahkan logic controller, validasi request, transformasi response, dan model database.

Contoh PostResource Lengkap

Berikut contoh resource yang menggabungkan beberapa konsep yang sudah dibahas:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class PostResource extends JsonResource
{
    public function toArray(Request $request): array
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'content' => $this->content,
            'excerpt' => str($this->content)->limit(120),
            'created_at' => $this->created_at?->toISOString(),
            'updated_at' => $this->updated_at?->toISOString(),

            'author' => new UserResource(
                $this->whenLoaded('user')
            ),
        ];
    }
}

Dengan resource tersebut, API memiliki struktur output yang lebih terkontrol.

Contoh Controller dengan API Resource

Controller dapat dibuat seperti:

<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Resources\PostResource;
use App\Models\Post;
use Illuminate\Http\Request;

class PostController extends Controller
{
    public function index()
    {
        $posts = Post::with('user')
            ->latest()
            ->paginate(10);

        return PostResource::collection($posts);
    }

    public function show(Post $post)
    {
        $post->load('user');

        return new PostResource($post);
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'title' => ['required', 'string', 'max:255'],
            'content' => ['required', 'string'],
        ]);

        $post = Post::create($validated);

        return new PostResource($post);
    }
}

Controller tetap relatif ringkas karena transformasi response dipindahkan ke Resource.

API Resource vs response()->json()

Keduanya dapat digunakan untuk membuat JSON response, tetapi memiliki tujuan yang berbeda.

response()->json() cocok untuk response sederhana:

return response()->json([
    'message' => 'Berhasil.',
]);

API Resource lebih cocok ketika response berasal dari model atau collection dan membutuhkan transformasi yang konsisten:

return new PostResource($post);

Untuk aplikasi kecil, response()->json() mungkin sudah cukup. Untuk API yang berkembang, API Resource membantu menjaga struktur response tetap terorganisir.

Praktik Terbaik Laravel API Resource

Beberapa praktik yang sebaiknya diterapkan:

  • Tentukan field API secara eksplisit.
  • Jangan mengembalikan seluruh model jika tidak diperlukan.
  • Pisahkan Resource berdasarkan kebutuhan domain.
  • Gunakan Resource Collection untuk collection.
  • Gunakan pagination untuk dataset besar.
  • Gunakan whenLoaded() untuk relationship opsional.
  • Gunakan eager loading untuk menghindari N+1 query.
  • Jangan menaruh business logic kompleks di Resource.
  • Gunakan Form Request untuk validasi input.
  • Gunakan Policy atau Gate untuk authorization.
  • Pertahankan struktur response yang konsisten.
  • Dokumentasikan kontrak API yang digunakan frontend.

API Resource sebaiknya tetap fokus pada transformasi data. Business logic yang kompleks lebih baik ditempatkan pada service, action, model, atau layer aplikasi yang sesuai.

Kesalahan yang Sering Terjadi

Mengembalikan Semua Field Model

Hindari:

return $this->resource->toArray();

jika model memiliki field yang tidak seharusnya menjadi bagian dari API.

Lebih baik tentukan field secara eksplisit:

return [
    'id' => $this->id,
    'title' => $this->title,
];

Relationship Menyebabkan Banyak Query

Jika Resource membutuhkan relationship:

$this->user

pastikan relationship telah di-load ketika memang dibutuhkan.

Gunakan:

Post::with('user')->get();

dan:

$this->whenLoaded('user')

Menggunakan Resource untuk Validasi

API Resource bukan tempat utama untuk validasi input.

Validasi sebaiknya dilakukan pada Request atau Form Request:

$request->validate([
    'title' => ['required', 'string'],
]);

Response Tidak Konsisten

Hindari endpoint yang satu menggunakan:

{
    "data": {}
}

sementara endpoint lain langsung mengembalikan:

{
    "id": 1
}

Pilih pola response yang sesuai dengan desain API dan gunakan secara konsisten.

Kesimpulan

Laravel API Resource merupakan fitur penting untuk membangun REST API dengan response JSON yang terstruktur dan konsisten. Resource memberikan lapisan transformasi antara Eloquent Model dan client sehingga developer dapat menentukan dengan jelas data apa yang boleh dikirim.

Dengan API Resource, kita dapat mengatur field response, mengubah nama atribut, memformat tanggal, menambahkan field turunan, menampilkan relationship secara conditional, mengelola collection, pagination, metadata, dan link.

Untuk aplikasi Laravel yang berkembang, penggunaan API Resource bersama Form Request, eager loading, authentication, authorization, dan pagination dapat menghasilkan API yang lebih mudah dipelihara dan dikonsumsi oleh frontend maupun aplikasi mobile.

FAQ

Apa itu Laravel API Resource?

Laravel API Resource adalah mekanisme untuk mengubah model atau collection Laravel menjadi struktur response JSON yang dapat dikontrol oleh developer.

Apa keuntungan menggunakan API Resource?

API Resource membuat response lebih konsisten, mengontrol field yang dikirim, membantu menyembunyikan data yang tidak diperlukan, dan memisahkan struktur API dari struktur database.

Apakah API Resource wajib digunakan di Laravel?

Tidak. Laravel tetap dapat mengembalikan response menggunakan response()->json(). Namun, API Resource sangat berguna untuk REST API yang memiliki banyak endpoint atau struktur response yang kompleks.

Apakah API Resource bisa digunakan untuk pagination?

Ya. PostResource::collection() dapat digunakan bersama hasil paginate() dan Laravel akan menyediakan metadata serta link pagination.

Bagaimana cara menampilkan relationship dalam API Resource?

Gunakan resource lain bersama whenLoaded(), kemudian eager load relationship dari controller menggunakan with() atau load().

Apakah API Resource digunakan untuk validasi?

Tidak. API Resource terutama digunakan untuk transformasi output. Validasi input sebaiknya dilakukan menggunakan Request validation atau Form Request.

Apakah API Resource dapat meningkatkan keamanan API?

API Resource dapat membantu mengurangi risiko data internal ikut terkirim karena developer menentukan field response secara eksplisit. Namun, API Resource bukan pengganti authentication dan authorization.