Tutorial Laravel #28: API Resource dan REST API Dasar

1. Membangun REST API dengan Laravel

Laravel sangat cocok untuk membangun REST API. Dengan Route::apiResource, Sanctum untuk auth, dan API Resource untuk format response yang konsisten, kamu bisa bangun API yang rapi dengan cepat.

2. Setup Awal API

# Route API ada di routes/api.php
# Semua route di sini otomatis dapat prefix /api

# Install Sanctum untuk API authentication
composer require laravel/sanctum
php artisan vendor:publish --provider="LaravelSanctumSanctumServiceProvider"
php artisan migrate
// routes/api.php
use AppHttpControllersApiArtikelController;
use AppHttpControllersApiAuthController;
use IlluminateSupportFacadesRoute;

// Public routes
Route::post('/login', [AuthController::class, 'login']);
Route::post('/register', [AuthController::class, 'register']);

// Protected routes (butuh token)
Route::middleware('auth:sanctum')->group(function () {
    Route::post('/logout', [AuthController::class, 'logout']);
    Route::apiResource('artikel', ArtikelController::class);
});

3. API Resource - Format Response Konsisten

php artisan make:resource ArtikelResource
php artisan make:resource ArtikelCollection
<?php
// app/Http/Resources/ArtikelResource.php
namespace AppHttpResources;

use IlluminateHttpRequest;
use IlluminateHttpResourcesJsonJsonResource;

class ArtikelResource extends JsonResource
{
    public function toArray(Request $request): array
    {
        return [
            'id'          => $this->id,
            'judul'       => $this->judul,
            'slug'        => $this->slug,
            'konten'      => $this->konten,
            'status'      => $this->status,
            'views'       => $this->views,
            'gambar_url'  => $this->gambar ? asset('storage/' . $this->gambar) : null,
            'penulis'     => [
                'id'   => $this->user->id,
                'nama' => $this->user->name,
            ],
            'tags'        => $this->tags->pluck('nama'),
            'dibuat'      => $this->created_at->format('d M Y H:i'),
            'diperbarui'  => $this->updated_at->diffForHumans(),
        ];
    }
}

4. API Controller

<?php
// app/Http/Controllers/Api/ArtikelController.php
namespace AppHttpControllersApi;

use AppHttpControllersController;
use AppHttpResourcesArtikelResource;
use AppModelsArtikel;
use IlluminateHttpRequest;

class ArtikelController extends Controller
{
    public function index()
    {
        $artikels = Artikel::with(['user', 'tags'])
                           ->where('status', 'published')
                           ->latest()
                           ->paginate(10);

        return ArtikelResource::collection($artikels);
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'judul'  => 'required|string|max:200',
            'konten' => 'required|string',
            'status' => 'required|in:draft,published',
        ]);

        $artikel = Artikel::create(array_merge($validated, [
            'user_id' => auth()->id(),
        ]));

        return new ArtikelResource($artikel);
        // Response: 200 OK
    }

    public function show(Artikel $artikel)
    {
        return new ArtikelResource($artikel->load(['user', 'tags']));
    }

    public function update(Request $request, Artikel $artikel)
    {
        $this->authorize('update', $artikel);

        $artikel->update($request->validate([
            'judul'  => 'sometimes|string|max:200',
            'konten' => 'sometimes|string',
            'status' => 'sometimes|in:draft,published',
        ]));

        return new ArtikelResource($artikel);
    }

    public function destroy(Artikel $artikel)
    {
        $this->authorize('delete', $artikel);
        $artikel->delete();
        return response()->json(['message' => 'Artikel berhasil dihapus'], 200);
    }
}

5. Auth Controller untuk API

<?php
namespace AppHttpControllersApi;

use AppModelsUser;
use IlluminateHttpRequest;
use IlluminateSupportFacadesAuth;

class AuthController extends Controller
{
    public function login(Request $request)
    {
        $request->validate([
            'email'    => 'required|email',
            'password' => 'required',
        ]);

        if (!Auth::attempt($request->only('email', 'password'))) {
            return response()->json(['message' => 'Kredensial tidak valid'], 401);
        }

        $user  = auth()->user();
        $token = $user->createToken('api-token')->plainTextToken;

        return response()->json([
            'user'  => ['id' => $user->id, 'nama' => $user->name, 'email' => $user->email],
            'token' => $token,
        ]);
    }

    public function logout(Request $request)
    {
        $request->user()->currentAccessToken()->delete();
        return response()->json(['message' => 'Berhasil logout']);
    }
}

6. Ringkasan

  • Gunakan routes/api.php dan Route::apiResource() untuk API route
  • API Resource memformat response secara konsisten dan menyembunyikan field internal
  • Laravel Sanctum untuk token-based authentication di API
  • Selalu return status code yang tepat: 200 OK, 201 Created, 401 Unauthorized, 403 Forbidden, 404 Not Found

Tutorial berikutnya membahas error handling dan logging di Laravel.


ariq fadhil

Im Ariq Tech, a Top Rated Fullstack Developer with 5+ years of experience, delivering high-quality solutions across 50+ projects.