Tahap III – Mini Project Real: AitiCore Flex Jadi Backend API (Endpoint JSON)
Di tahap ini kita bikin AitiCore Flex jadi backend API beneran. Targetnya: kamu paham konsep API, endpoint, request/response JSON, dan CRUD sederhana lewat HTTP. Bahasanya santai, tapi teknisnya dapet.
1) Gambaran Mini Project
Kita bikin API untuk data produk.
- GET /api/products → list produk
- GET /api/products/{id} → detail produk
- POST /api/products → tambah produk
- PUT /api/products/{id} → update produk
- DELETE /api/products/{id} → hapus produk
Outputnya JSON, jadi bisa dipakai frontend apa pun: Next.js, Nuxt, React, Flutter, bahkan Postman.
2) Siapkan Database (MySQL)
Buat database:
CREATE DATABASE aiticore_api;
Buat tabel products:
CREATE TABLE products (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(150) NOT NULL,
price DECIMAL(12,2) NOT NULL DEFAULT 0,
stock INT NOT NULL DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Isi data contoh:
INSERT INTO products (name, price, stock) VALUES
('Oli Mesin', 45000, 20),
('Busi', 18000, 50);
3) Bikin Routing Endpoint API
Edit file routes:
routes/web.php
Tambahin endpoint API:
$router->get('/api/products', 'ApiProductController@index');
$router->get('/api/products/{id}', 'ApiProductController@show');
$router->post('/api/products', 'ApiProductController@store');
$router->put('/api/products/{id}', 'ApiProductController@update');
$router->delete('/api/products/{id}', 'ApiProductController@destroy');
Catatan: Kalau router kamu belum support PUT/DELETE, biasanya karena server PHP native cuma gampang baca GET/POST. Solusi pelajar: pakai POST + method spoofing (dibahas di bagian 7).
4) Buat Controller API (Output JSON)
Buat file:
app/Controllers/ApiProductController.php
<?php
namespace App\Controllers;
use App\Models\ProductModel;
class ApiProductController
{
private $product;
public function __construct()
{
$this->product = new ProductModel();
}
private function json($data, $status = 200)
{
http_response_code($status);
header('Content-Type: application/json; charset=utf-8');
echo json_encode($data);
exit;
}
// GET /api/products
public function index()
{
$items = $this->product->all();
$this->json([
'success' => true,
'data' => $items
]);
}
// GET /api/products/{id}
public function show($id)
{
$item = $this->product->find($id);
if (!$item) {
$this->json(['success' => false, 'message' => 'Produk tidak ditemukan'], 404);
}
$this->json(['success' => true, 'data' => $item]);
}
// POST /api/products
public function store()
{
$payload = json_decode(file_get_contents('php://input'), true);
$name = $payload['name'] ?? '';
$price = $payload['price'] ?? 0;
$stock = $payload['stock'] ?? 0;
if ($name === '') {
$this->json(['success' => false, 'message' => 'name wajib diisi'], 422);
}
$id = $this->product->insert([
'name' => $name,
'price' => $price,
'stock' => $stock
]);
$this->json(['success' => true, 'message' => 'Produk dibuat', 'id' => $id], 201);
}
// PUT /api/products/{id}
public function update($id)
{
$payload = json_decode(file_get_contents('php://input'), true);
$item = $this->product->find($id);
if (!$item) {
$this->json(['success' => false, 'message' => 'Produk tidak ditemukan'], 404);
}
$name = $payload['name'] ?? $item['name'];
$price = $payload['price'] ?? $item['price'];
$stock = $payload['stock'] ?? $item['stock'];
$this->product->update($id, [
'name' => $name,
'price' => $price,
'stock' => $stock
]);
$this->json(['success' => true, 'message' => 'Produk diupdate']);
}
// DELETE /api/products/{id}
public function destroy($id)
{
$item = $this->product->find($id);
if (!$item) {
$this->json(['success' => false, 'message' => 'Produk tidak ditemukan'], 404);
}
$this->product->delete($id);
$this->json(['success' => true, 'message' => 'Produk dihapus']);
}
}
Intinya: controller API itu sama kayak controller biasa, bedanya dia tidak return view HTML, tapi echo JSON.
5) Buat Model ProductModel (Akses Database)
Buat file:
app/Models/ProductModel.php
<?php
namespace App\Models;
class ProductModel
{
private $db;
public function __construct()
{
// Sesuaikan cara ambil koneksi DB sesuai AitiCore Flex kamu
// Misal ada helper db() atau config database.
$this->db = db();
}
public function all()
{
$sql = "SELECT id, name, price, stock, created_at FROM products ORDER BY id DESC";
return $this->db->query($sql)->fetchAll(\PDO::FETCH_ASSOC);
}
public function find($id)
{
$stmt = $this->db->prepare("SELECT id, name, price, stock, created_at FROM products WHERE id = ?");
$stmt->execute([$id]);
return $stmt->fetch(\PDO::FETCH_ASSOC);
}
public function insert($data)
{
$stmt = $this->db->prepare("INSERT INTO products (name, price, stock) VALUES (?, ?, ?)");
$stmt->execute([$data['name'], $data['price'], $data['stock']]);
return (int)$this->db->lastInsertId();
}
public function update($id, $data)
{
$stmt = $this->db->prepare("UPDATE products SET name = ?, price = ?, stock = ? WHERE id = ?");
return $stmt->execute([$data['name'], $data['price'], $data['stock'], $id]);
}
public function delete($id)
{
$stmt = $this->db->prepare("DELETE FROM products WHERE id = ?");
return $stmt->execute([$id]);
}
}
Poin belajar: Model itu cuma tempat query. Biar controller kamu gak jadi “mie instan” (campur semua).
6) Cara Test Endpoint (Pakai Curl)
List produk:
curl http://localhost:8000/api/products
Detail produk id=1:
curl http://localhost:8000/api/products/1
Tambah produk (POST JSON):
curl -X POST http://localhost:8000/api/products ^
-H "Content-Type: application/json" ^
-d "{\"name\":\"Kampas Rem\",\"price\":25000,\"stock\":10}"
Kalau kamu pakai Linux/Mac, tanda ^ diganti \ (backslash).
7) Kalau Router Belum Support PUT/DELETE (Cara Pelajar)
Gampang: kamu bikin update/delete pakai POST saja.
Contoh routing alternatif:
$router->post('/api/products/{id}/update', 'ApiProductController@update');
$router->post('/api/products/{id}/delete', 'ApiProductController@destroy');
Jadi frontend tinggal POST aja. Nanti kalau udah paham, baru rapihin jadi PUT/DELETE beneran.
8) Biar API Kamu “Layak Dipakai” (Versi Pelajar)
- Response konsisten: selalu pakai format { success, message, data }
- Status code bener: 200 OK, 201 Created, 404 Not Found, 422 Validation Error
- Validasi minimal: cek field wajib
- Jangan echo HTML: API harus JSON
9) Next Upgrade Setelah Ini
- Token Auth sederhana (API Key / Bearer token)
- Pagination untuk list endpoint
- Search & filter (misal: ?q=oli)
- Rate limit basic (biar gak di-spam)
Kesimpulan
Di Tahap III ini, AitiCore Flex sudah jadi backend API yang bisa dipakai untuk aplikasi real. Kamu belajar routing, controller, model, database, dan response JSON yang rapih.
Kalau kamu udah bisa bikin ini, kamu bukan “belajar PHP” lagi. Kamu udah mulai “ngoding aplikasi beneran”.