API: Resource, JSON:API & Sanctum
Membangun REST API: API Resource untuk membentuk JSON, JSON:API Resources Laravel 13, dan autentikasi token dengan Sanctum.
Menyiapkan API
php artisan install:api # membuat routes/api.php, menginstal Sanctum, menambah migrasi token
Route di routes/api.php otomatis berawalan /api dan tanpa session/CSRF (stateless): klien mengirim token di tiap permintaan.
API Resource: lapisan transformasi
Mengembalikan model Eloquent langsung (return $produk;) membocorkan semua kolom dan terikat pada struktur database. API Resource adalah lapisan di antara model dan JSON: kamu memutuskan persis bentuk responsnya.
php artisan make:resource ProdukResource
php artisan make:resource ProdukCollection --collection
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class ProdukResource extends JsonResource
{
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'nama' => $this->nama,
'slug' => $this->slug,
'harga' => $this->harga,
'harga_rupiah' => $this->harga_rupiah, // accessor model
'tersedia' => $this->stok > 0,
'kategori' => new KategoriResource($this->whenLoaded('kategori')), // hanya bila sudah dimuat
'dibuat_pada' => $this->created_at->toIso8601String(),
];
}
}
$this->namamengakses atribut model yang dibungkus.whenLoaded('kategori')menyertakan relasi hanya jika sudah di-eager-load (mencegah N+1 tak sengaja).- Atribut kondisional:
$this->when($user->isAdmin(), fn () => $this->harga_modal).
Memakai resource di controller
public function index()
{
return ProdukResource::collection(Produk::with('kategori')->paginate(15)); // + meta & links paginasi otomatis
}
public function show(Produk $produk): ProdukResource
{
return new ProdukResource($produk->load('kategori'));
}
Respons dibungkus dalam kunci data: { "data": { ... } }; koleksi berpaginasi menambah links dan meta. Cara singkat: $produk->toResource().
JSON:API Resources — baru di Laravel 13
Laravel 13 menyertakan JsonApiResource yang menghasilkan respons sesuai standar JSON:API (Content-Type: application/vnd.api+json), lengkap dengan id, type, attributes, relasi, sparse fieldsets, dan include.
php artisan make:resource PostResource --json-api
use Illuminate\Http\Resources\JsonApi\JsonApiResource;
class PostResource extends JsonApiResource
{
public $attributes = ['title', 'body', 'created_at'];
public $relationships = ['author', 'comments']; // hanya disertakan bila klien meminta ?include=
}
Route::get('/api/posts/{post}', fn (Post $post) => new PostResource($post)); // GET /api/posts/1?include=author
Keluaran: { "data": { "id": "1", "type": "posts", "attributes": { ... } } }. Cocok bila klienmu (mis. pustaka front end) mengharapkan format JSON:API.
Autentikasi API: Laravel Sanctum
Sanctum menyediakan token API sederhana (dan autentikasi SPA berbasis cookie). Tambahkan trait ke model User:
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens;
}
// Login → menerbitkan token
public function login(Request $request): JsonResponse
{
$user = User::where('email', $request->email)->first();
if (! $user || ! Hash::check($request->password, $user->password)) {
return response()->json(['pesan' => 'Kredensial salah'], 401);
}
return response()->json(['token' => $user->createToken('mobile')->plainTextToken]);
}
// Melindungi route
Route::middleware('auth:sanctum')->group(function () {
Route::apiResource('produk', ProdukApiController::class);
});
Klien mengirim Authorization: Bearer <token>. Token hanya terlihat sekali (plainTextToken); database menyimpan hash-nya. Cabut: $user->currentAccessToken()->delete(). Batasi dengan abilities: createToken('mobile', ['produk:baca']) dan cek $user->tokenCan('produk:baca').
Praktik baik API
- Versi API:
Route::prefix('v1'). - Kode status tepat (201, 204, 401, 403, 404, 422).
- Paginasi untuk semua daftar; rate limiting (
throttle:api). - Eager loading +
whenLoadeduntuk menghindari N+1. - Jangan pernah mengembalikan password/hash/token rahasia.