Pendahuluan — dari pintu ke loket & dapur

Artikel ini adalah #60 (ini) di Seri 4: Pemrograman Web Lanjut v2. Di Request & Form Request: Menjaga Input API (#59) kamu sudah punya satpam di pintu. Sekarang langkah 5/8: pindahkan kerja dari file route ke Controller (loket), Service (dapur), dan Eloquent (cara baca baris di tabel).

Awam: kalau semua aturan ditulis di routes/web.php, file pintu cepat penuh. Loket menerima tamu, dapur menyiapkan daftar buku, rak (tabel) menyimpan data. Kita pisahkan biar rapi.

Domain tetap perpustakaan mini. Hari ini fokus: daftar buku lewat Controller + Service, lalu baca dari tabel dengan model Eloquent. Login/auth datang di langkah berikutnya.

Prasyarat: sudah selesai Request & Form Request: Menjaga Input API (#59) dan Routing & Jawaban JSON API Perpustakaan (#58)GET /api/buku pernah jalan. Fondasi di Struktur Folder, .env & Artisan Laravel (#57) dan Instal PHP, Composer & Proyek Laravel (#56). Pakai Laravel 13+ — butuh PHP 8.3+.

Spesifikasi fitur — apa yang kita kuasai?

Daftar singkat yang bisa kamu centang di akhir artikel:

  1. Membuat Controller dengan Artisan dan menghubungkan route ke loket.
  2. Membuat Service sederhana yang menyiapkan daftar buku.
  3. Mengenal Eloquent (model) sebagai cara baca baris di tabel bukus.
  4. Menguji GET /api/buku di browser setelah php artisan serve hidup.

Awam: urutan nyaman: buka alat -> buat model/tabel -> buat service -> buat controller -> hubungkan route -> uji di browser. Belum perlu login.

Istilah — ringkas untuk loket, dapur, rak

Istilah Arti awam Contoh di artikel ini
Controller Loket — menerima permintaan, memanggil dapur, mengembalikan jawaban BukuController
Service Dapur — aturan bisnis ringan (ambil daftar buku) BukuService
Eloquent / Model Cara bicara ke tabel database lewat class PHP Buku::query()->get()
Migrasi Cetak biru tabel yang dijalankan Artisan php artisan migrate

Urutan belajar: kenali tiga peran -> buat file -> hubungkan route -> uji JSON.

Kenapa pindah dari route?

Di artikel routing & validasi sebelumnya, banyak logika masih di routes/web.php. Itu bagus untuk belajar pintu. Begitu daftar buku + validasi + tabel bertambah, pintu jadi ramai.

Awam: sama seperti perpustakaan — satpam tetap di pintu, tapi petugas loket dan dapur punya meja sendiri. Route hanya menunjuk: “tamu daftar buku -> ke loket BukuController”.

Artikel ini tetap install-dari-nol untuk file baru: kita pakai Artisan make:model / make:controller dan membuat Service manual. Tidak ada paket Composer baru. Fondasi tetap merujuk Instal PHP, Composer & Proyek Laravel (#56).

Alur — dari URL sampai daftar buku

Alur: Browser -> Controller -> Service -> Eloquent/tabel Alur: Browser -> Controller -> Service -> Tabel Browser GET /api/buku Controller loket Service dapur Tabel Eloquent Setelah validasi: pindahkan daftar buku ke loket + dapur, baca dari tabel, lalu uji lagi di browser. Login/auth datang belakangan. Urutan ini mengikuti langkah #60 (ini) — belum auth API.
#60 (ini): browser -> controller -> service -> Eloquent/tabel.

Persiapan — alat yang kamu buka

Alat yang dipakai di artikel ini (sudah dari fondasi Instal PHP, Composer & Proyek Laravel (#56) / Struktur Folder, .env & Artisan Laravel (#57) — tidak ada unduhan wajib baru):

  • Explorer — melihat folder app, database/migrations, dan membuat folder app/Services jika belum ada.
  • Terminal — Laragon: menu Terminal · XAMPP: tombol Shell. Untuk cd, php artisan serve, make:model, make:controller, dan migrate. Jangan asal buka CMD/PowerShell dari Start Menu.
  • Terminal kedua — wajib hari ini: terminal pertama menjalankan serve (lampu toko). Terminal kedua untuk Artisan make:… dan perintah lain tanpa mematikan lampu.
  • Editor teks — Notepad / VS Code — membuka file Controller, Service, Model, migrasi, dan routes/web.php. Cara cepat Windows: notepad path\ke\file.php dari terminal kedua.
  • Browser — menguji http://127.0.0.1:8000/api/buku setelah loket terhubung.

Buka terminal Laragon/Shell XAMPP, masuk folder proyek dulu:

cd C:\laragon\www\perpustakaan-api

Di XAMPP biasanya: cd C:\xampp\htdocs\perpustakaan-api. Sesuaikan path jika foldermu beda.

Nyalakan lampu toko di terminal pertama:

php artisan serve

Biarkan jendela itu hidup. Buka terminal kedua (Laragon/Shell lagi), cd ke folder proyek yang sama — di sini kamu mengetik perintah Artisan berikutnya.

Awam: Terminal 1 = lampu toko. Terminal 2 = tangan membuat file & migrasi. Editor = menulis isi loket/dapur. Browser = melihat slip JSON. Matikan serve dengan Ctrl+C hanya di terminal yang menjalankannya.

Model & tabel — Eloquent dari nol

Di terminal kedua (folder perpustakaan-api):

php artisan make:model Buku -m

Artisan membuat dua berkas: model app/Models/Buku.php dan file migrasi di database/migrations/ (nama berisi create_bukus_table).

Buka file migrasi di editor. Cara awam:

  1. Explorer: masuk folder database/migrations, pilih file terbaru yang namanya mengandung create_bukus_table, buka dengan Notepad/VS Code.
  2. Atau terminal kedua — daftar dulu, lalu buka dengan nama yang muncul:
dir database\migrations
notepad database\migrations\nama_file_create_bukus_table.php

Ganti nama_file_create_bukus_table.php dengan nama lengkap dari hasil dir. Di dalam fungsi up(), pastikan ada kolom sederhana (sesuaikan cuplikan ke kerangka yang Artisan buat):

// Cuplikan migrasi — kolom judul & penulis
$table->id();
$table->string('judul');
$table->string('penulis');
$table->timestamps();

Simpan, lalu di terminal kedua:

php artisan migrate

Buka model di editor (dari terminal kedua: notepad app\Models\Buku.php). Tambahkan daftar kolom yang boleh diisi massal (cuplikan — tempel di dalam class):

// Cuplikan app/Models/Buku.php
protected $fillable = ['judul', 'penulis'];

Awam: Eloquent = cara Laravel membaca/menulis baris tabel lewat class Model. Buku = cetakan satu baris buku. migrate = membangun rak tabel di database (SQLite dari fondasi denah sudah cukup).

Install-dari-nol: tidak perlu driver ekstra. Pastikan DB_CONNECTION=sqlite dan file database/database.sqlite sudah ada seperti di Struktur Folder, .env & Artisan Laravel (#57).

Service — dapur daftar buku

Buat folder app/Services jika belum ada. Di terminal kedua (masih di folder proyek):

mkdir app\Services

Kalau terminal bilang folder sudah ada — lanjut saja, itu normal. Lalu buat file app/Services/BukuService.php (paling mudah: notepad app\Services\BukuService.php, tempel cuplikan di bawah, simpan):

<?php

namespace App\Services;

use App\Models\Buku;
use Illuminate\Support\Collection;

class BukuService
{
    public function daftar(): Collection
    {
        return Buku::query()->orderBy('id')->get(['id', 'judul', 'penulis']);
    }
}

Awam: Service = dapur. Loket tidak perlu tahu cara query tabel — cukup minta daftar(). Kalau tabel masih kosong, JSON data bisa berupa array kosong — itu normal; isi baris buku boleh belakangan (bukan wajib hari ini).

Controller — loket

Masih di terminal kedua:

php artisan make:controller BukuController

Buka app/Http/Controllers/BukuController.php di editor (boleh notepad app\Http\Controllers\BukuController.php). Jangan hapus baris namespace dan kerangka class BukuController extends Controller. Tambahkan baris use di atas class, lalu tempel method index di dalam class:

// Cuplikan BukuController — loket daftar buku
use App\Services\BukuService;
use Illuminate\Http\JsonResponse;

public function index(BukuService $bukuService): JsonResponse
{
    return response()->json([
        'message' => 'Daftar buku perpustakaan mini',
        'data' => $bukuService->daftar(),
    ]);
}

Awam: parameter BukuService $bukuService diisi otomatis oleh Laravel (seperti dipanggilkan ke dapur). Loket hanya menyusun jawaban JSON.

Hubungkan route ke loket

Buka routes/web.php di editor (atau notepad routes\web.php dari terminal kedua). Ganti / sesuaikan route GET daftar buku menjadi:

// Cuplikan routes/web.php — arahkan ke Controller
use App\Http\Controllers\BukuController;

Route::get('/api/buku', [BukuController::class, 'index']);

Simpan file. Pastikan php artisan serve masih hidup di terminal pertama.

Awam: baris itu artinya: tamu yang GET /api/buku dilayani loket BukuController fungsi index — bukan lagi fungsi panjang di dalam file route.

Uji di browser

Dengan serve masih hidup, buka browser ke:

http://127.0.0.1:8000/api/buku

Kamu harus melihat JSON berisi message dan data. Kalau tabel masih kosong, data bisa [] — struktur tetap benar. Kalau error class tidak ditemukan, cek: file Service/Controller sudah disimpan? Nama folder Services huruf besar S? Sudah cd di proyek yang sama?

Awam: browser = mata melihat slip. Terminal = tangan membuat file. Jangan menguji URL sebelum serve hidup.

Pola Dasar — empat langkah loket bersih

  1. 1
    Buka alat
    Terminal 1 serve · Terminal 2 Artisan · Editor · Browser.
  2. 2
    Model + migrate
    make:model Buku -m lalu isi kolom & migrate.
  3. 3
    Service + Controller
    Dapur daftar() · loket index mengembalikan JSON.
  4. 4
    Route + uji
    Arahkan GET /api/buku ke Controller, cek di browser.

Demo loket & dapur — file mandiri

Latihan ide tanpa mengubah proyek Laravel:

  1. Buka editor teks, buat file baru, tempel cuplikan di bawah, simpan sebagai laravel_controller_service_eloquent_demo.php (boleh di Desktop).
  2. Buka terminal di folder tempat file itu disimpan (Explorer: Shift+klik kanan -> “Open in Terminal” / “Buka di Terminal”, atau cd manual). Pastikan php -v sudah jalan.
  3. Jalankan: php laravel_controller_service_eloquent_demo.php — layar menampilkan simulasi loket -> dapur -> daftar buku.

File ini mensimulasikan peran — tidak mengubah proyek Laravel-mu:

<?php

declare(strict_types=1);

/**
 * Demo loket (Controller) & dapur (Service) — simulasi teks untuk awam.
 */

function dapurDaftarBuku(): array
{
    return [
        ['id' => 1, 'judul' => 'Belajar PHP', 'penulis' => 'Ayu'],
        ['id' => 2, 'judul' => 'Dasar Laravel', 'penulis' => 'Budi'],
    ];
}

function loketIndex(): array
{
    return [
        'message' => 'Daftar buku perpustakaan mini',
        'data' => dapurDaftarBuku(),
    ];
}

function demo(): void
{
    echo "=== Simulasi loket -> dapur ===", PHP_EOL;
    echo json_encode(loketIndex(), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE), PHP_EOL;
    echo PHP_EOL, "Langkah sungguhan: Model+migrate -> BukuService -> BukuController -> route -> browser.", PHP_EOL;
}

demo();

Awam: demo() hanya menampilkan JSON contoh di terminal. Setelah paham, kerjakan langkah sungguhan di folder perpustakaan-api. declare(strict_types=1); membuat tipe lebih ketat — boleh diikuti, tidak wajib dihafal.

Kesalahan umum

Gejala Penyebab tipikal Perbaikan awam
Class BukuService not found File/folder salah atau belum disimpan Cek path app/Services/BukuService.php dan huruf besar S
Connection refused serve belum hidup Nyalakan di terminal pertama setelah cd ke proyek
Bingung perintah diketik di mana Terminal salah / Start Menu Lihat Persiapan — alat yang kamu buka; pakai Laragon/Shell XAMPP
Tabel/migrate error SQLite belum siap atau DB_CONNECTION masih mysql Kembali ke Struktur Folder, .env & Artisan Laravel (#57): file database.sqlite + DB_CONNECTION=sqlite
Bingung file migrasi mana yang dibuka Banyak file di folder migrations Pilih yang namanya mengandung create_bukus_table — pakai dir database\migrations atau Explorer
data kosong [] Tabel belum diisi baris Normal di awal — struktur JSON sudah benar; isi data belakangan

Latihan

  1. Jalankan demo PHP di atas, lalu bandingkan strukturnya dengan JSON di browser setelah Controller hidup.
  2. Jelaskan ke teman: beda singkat loket (Controller), dapur (Service), dan rak (Eloquent/tabel).
  3. Pastikan kamu bisa mengulang: terminal 1 serve, terminal 2 make:…, editor simpan, browser uji.

FAQ

Terminal mana yang harus dibuka?
Laragon: menu Terminal · XAMPP: tombol Shell. Lalu cd ke perpustakaan-api. Satu jendela untuk serve, jendela kedua untuk Artisan.

Harus VS Code?
Tidak. Notepad cukup untuk menempel cuplikan. Dari terminal kedua: notepad app\Services\BukuService.php atau path file lain. VS Code membantu kalau kamu suka.

File migrasi yang mana?
Setelah make:model Buku -m, di terminal kedua ketik dir database\migrations — pilih file yang namanya mengandung create_bukus_table, lalu notepad database\migrations\…. Atau lewat Explorer ke folder yang sama.

Kenapa Service dibuat manual?
Supaya awam melihat folder app/Services dengan jelas. Intinya: dapur = class berisi fungsi daftar buku.

Apa itu Eloquent tanpa istilah sulit?
Eloquent = cara membaca/menulis tabel lewat model PHP. Buku::query()->get() ≈ “ambil semua baris buku”.

Apa hubungan dengan artikel validasi?
Request & Form Request: Menjaga Input API (#59) menjaga slip masuk. #60 (ini) merapikan siapa yang melayani daftar buku (loket + dapur + tabel).

Ke mana setelah ini?
Berikutnya: Auth API Dasar: Login & Kartu Anggota (#61) — kartu anggota supaya tidak semua orang boleh masuk pintu staf.

Kesimpulan

Kamu sudah memindahkan daftar buku ke pola rapi: Controller (loket), Service (dapur), Eloquent (baca tabel), diuji lewat browser saat artisan serve hidup. Ini langkah 5/8 jalur Laravel di Seri 4.

Seri 4 progress: langkah #60 (ini) · 5/8 jalur Laravel · prasyarat: Request & Form Request: Menjaga Input API (#59) LIVE. Berikutnya: Auth API Dasar: Login & Kartu Anggota (#61).