Laravel API

Sampai di sini, semua halaman yang kita buat menggunakan Blade (HTML). Tapi bagaimana jika kamu ingin membuat backend yang melayani mobile app, frontend React/Vue, atau layanan lain?

Jawabannya: API (Application Programming Interface). Alih-alih mengembalikan HTML, API mengembalikan data JSON yang bisa dikonsumsi oleh siapa saja.

1. Web Route vs API Route

Laravel memisahkan dua jenis route:

FilePrefixUntukFormat Response
routes/web.php/Browser (HTML + Blade)HTML
routes/api.php/api/API (Mobile, SPA, Service)JSON
// routes/api.php

use App\Http\Controllers\Api\ProdukController;

// URL menjadi: /api/produk
Route::apiResource('produk', ProdukController::class);
apiResource vs resource

Route::apiResource() menghasilkan 5 route (tanpa create dan edit, karena API tidak butuh form HTML). Route::resource() menghasilkan 7 route (termasuk form).

2. Membuat API Controller

php artisan make:controller Api/ProdukController --api
<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Produk;
use Illuminate\Http\Request;

class ProdukController extends Controller
{
    // GET /api/produk
    public function index()
    {
        $produkList = Produk::latest()->paginate(10);
        return response()->json($produkList);
    }

    // POST /api/produk
    public function store(Request $request)
    {
        $validated = $request->validate([
            'nama'  => 'required|string|max:255',
            'harga' => 'required|numeric|min:1000',
        ]);

        $produk = Produk::create($validated);

        return response()->json([
            'message' => 'Produk berhasil ditambahkan!',
            'data'    => $produk,
        ], 201); // 201 = Created
    }

    // GET /api/produk/{id}
    public function show(Produk $produk)
    {
        return response()->json($produk);
    }

    // PUT /api/produk/{id}
    public function update(Request $request, Produk $produk)
    {
        $validated = $request->validate([
            'nama'  => 'required|string|max:255',
            'harga' => 'required|numeric|min:1000',
        ]);

        $produk->update($validated);

        return response()->json([
            'message' => 'Produk berhasil diupdate!',
            'data'    => $produk,
        ]);
    }

    // DELETE /api/produk/{id}
    public function destroy(Produk $produk)
    {
        $produk->delete();

        return response()->json([
            'message' => 'Produk berhasil dihapus.',
        ]);
    }
}

3. API Resource (Transformasi Data)

Kamu mungkin tidak ingin menampilkan semua kolom database ke API (misalnya: created_at, updated_at, atau kolom internal). Gunakan API Resource:

php artisan make:resource ProdukResource
<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class ProdukResource extends JsonResource
{
    public function toArray($request): array
    {
        return [
            'id'         => $this->id,
            'nama'       => $this->nama,
            'harga'      => $this->harga,
            'harga_formatted' => 'Rp ' . number_format($this->harga, 0, ',', '.'),
            'deskripsi'  => $this->deskripsi,
            'gambar_url' => $this->gambar ? asset('storage/' . $this->gambar) : null,
        ];
    }
}

Gunakan di controller:

use App\Http\Resources\ProdukResource;

public function index()
{
    $produkList = Produk::latest()->paginate(10);
    return ProdukResource::collection($produkList);
}

public function show(Produk $produk)
{
    return new ProdukResource($produk);
}

Response JSON yang dihasilkan akan rapi dan konsisten:

{
    "data": {
        "id": 1,
        "nama": "Kaos Polos Hitam",
        "harga": 89000,
        "harga_formatted": "Rp 89.000",
        "deskripsi": "Kaos cotton combed 30s",
        "gambar_url": "http://toko-keren.test/storage/produk/kaos.jpg"
    }
}

4. Autentikasi API dengan Sanctum

Untuk melindungi API agar hanya bisa diakses oleh user yang berhak, gunakan Laravel Sanctum:

# Install Sanctum
php artisan install:api

Proteksi route API:

// routes/api.php

use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;

// Route publik
Route::get('/produk', [ProdukController::class, 'index']);
Route::get('/produk/{produk}', [ProdukController::class, 'show']);

// Route yang butuh auth token
Route::middleware('auth:sanctum')->group(function () {
    Route::post('/produk', [ProdukController::class, 'store']);
    Route::put('/produk/{produk}', [ProdukController::class, 'update']);
    Route::delete('/produk/{produk}', [ProdukController::class, 'destroy']);

    // Endpoint untuk cek user yang sedang login
    Route::get('/user', function (Request $request) {
        return $request->user();
    });
});

Cara login via API dan mendapatkan token:

// routes/api.php
Route::post('/login', function (Request $request) {
    $credentials = $request->validate([
        'email'    => 'required|email',
        'password' => 'required',
    ]);

    if (!Auth::attempt($credentials)) {
        return response()->json(['message' => 'Email atau password salah.'], 401);
    }

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

    return response()->json([
        'message' => 'Login berhasil!',
        'token'   => $token,
        'user'    => $user,
    ]);
});

Client menggunakan token di setiap request:

# Contoh akses API dari terminal (curl)
curl -H "Authorization: Bearer 1|abc123tokenxyz" \
     -H "Accept: application/json" \
     http://toko-keren.test/api/produk

5. Mengonsumsi API Eksternal

Laravel juga punya built-in HTTP Client untuk memanggil API dari luar:

use Illuminate\Support\Facades\Http;

// GET request
$response = Http::get('https://api.github.com/users/laravolt');
$data = $response->json();

echo $data['name']; // "Laravolt"

// POST request dengan auth
$response = Http::withToken('your-api-token')
    ->post('https://api.example.com/orders', [
        'produk_id' => 1,
        'jumlah'    => 2,
    ]);

if ($response->successful()) {
    $order = $response->json();
    echo "Order #{$order['id']} berhasil dibuat!";
} else {
    echo "Error: " . $response->status();
}
HTTP Client vs cURL

Di PHP Native, kamu menggunakan curl_init() yang verbose dan sulit dibaca. Laravel HTTP Client menggunakan sintaks yang sangat bersih dan mendukung retry, timeout, dan error handling secara built-in.

6. HTTP Status Code yang Penting

CodeNamaKapan Digunakan
200OKRequest berhasil (GET, PUT)
201CreatedData baru berhasil dibuat (POST)
204No ContentBerhasil tapi tidak ada data (DELETE)
400Bad RequestRequest tidak valid
401UnauthorizedBelum login / token salah
403ForbiddenLogin tapi tidak punya akses
404Not FoundData tidak ditemukan
422UnprocessableValidasi gagal
500Server ErrorBug di server

7. Testing API dengan Pest

<?php

use App\Models\Produk;
use App\Models\User;

test('API mengembalikan daftar produk', function () {
    Produk::factory()->count(3)->create();

    $this->getJson('/api/produk')
        ->assertOk()
        ->assertJsonCount(3, 'data');
});

test('API bisa membuat produk baru', function () {
    $user = User::factory()->create();

    $this->actingAs($user, 'sanctum')
        ->postJson('/api/produk', [
            'nama'  => 'Kaos Baru',
            'harga' => 75000,
        ])
        ->assertCreated()
        ->assertJsonPath('data.nama', 'Kaos Baru');
});

test('API menolak request tanpa auth', function () {
    $this->postJson('/api/produk', [
        'nama'  => 'Kaos',
        'harga' => 50000,
    ])->assertUnauthorized(); // 401
});

8. Perbandingan: PHP Native vs Laravel API

AspekPHP NativeLaravel API
JSON Responsejson_encode() manualresponse()->json()
Routingif ($_SERVER['REQUEST_METHOD'])Route::apiResource()
ValidasiManual$request->validate()
Auth TokenImplementasi sendiriSanctum (built-in)
HTTP Clientcurl_init() 20+ barisHttp::get() 1 baris
TransformasiManual array mappingAPI Resources

Penutup

🎉 Selamat! Kamu telah menyelesaikan seluruh materi Laravel Hands-On. Kamu sekarang memahami:

  1. Validasi — Melindungi input user
  2. Auth — Sistem login dengan Breeze
  3. Middleware — Penjaga setiap route
  4. Resource Controller — CRUD dengan konvensi rapi
  5. Testing — Automated testing dengan Pest
  6. API — Membangun dan mengonsumsi API

Dari sini, kamu bisa memperdalam topik-topik lanjutan seperti Queues (background jobs), DTO (clean data handling), dan arsitektur domain-oriented untuk project skala besar.

Selamat ngoding, dan selamat berkarya dengan Laravel! 🚀