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:
// 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.',
]);
}
}
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
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
Penutup
🎉 Selamat! Kamu telah menyelesaikan seluruh materi Laravel Hands-On. Kamu sekarang memahami:
- ✅ Validasi — Melindungi input user
- ✅ Auth — Sistem login dengan Breeze
- ✅ Middleware — Penjaga setiap route
- ✅ Resource Controller — CRUD dengan konvensi rapi
- ✅ Testing — Automated testing dengan Pest
- ✅ 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! 🚀