La Ravel Phase 2
La Ravel Phase 2
Pembukaan 5
Changelogs 7
v1.2.0 (15 Mei 2025) - Rilis Phase 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
v1.0.0 (12 Maret 2025) - Rilis Awal . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2
Laravel Repository Pattern 37
What is Repository Pattern? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Implementasi Repository Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . 38
Buat Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
Implementasi Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
Implementasi Controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
3
Menyusun Routing untuk Project Besar 68
Berbagai File Router dan Kegunaan-nya . . . . . . . . . . . . . . . . . . . . . . . . . 68
Maksimalkan router Laravel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
Menggunakan named router . . . . . . . . . . . . . . . . . . . . . . . . . . 69
Menggunakan resource router untuk CRUD . . . . . . . . . . . . . . . . 70
Menggunakan route model binding . . . . . . . . . . . . . . . . . . . . . . 71
Memisahkan file router sesuai context . . . . . . . . . . . . . . . . . . . . 72
Jangan gunakan clousure file routing . . . . . . . . . . . . . . . . . . . . . 74
4
Pembukaan
Sebagai developer Laravel, seringkali kita menghadapi beberapa masalah seperti: kode yang
sulit dibaca, performa aplikasi yang menurun seiring pertumbuhan pengguna, struktur kode
yang makin rumit, dan masih banyak lagi.
Masalah ini seringkali disebabkan oleh kurangnya pemahaman terhadap best practice dalam
pengembangan aplikasi Laravel. Maka dari itu saya menulis buku dengan judul “Belajar
Membuat Aplikasi Laravel Sesuai Standar Best Practice” Harapan saya buku ini hadir
untuk membantu mengatasi masalah yang muncul dalam pengembangan aplikasi, selain itu
juga membantu developer Laravel berkembang lebih baik lagi dengan tidak hanya fokus pada
pengembangan aplikasi saja, tetapi juga memperhatikan best practice dalam pengembangan
aplikasi.
Buku ini berisi berbagai best practices yang bisa langsung diterapkan, mulai dari tips pengelo-
laan kode, desain arsitektur, hingga teknik optimalisasi performa dan keamanan
Ebook ini cocok untuk semua tingkatan developer Laravel: dari pemula yang ingin menerapkan
standar yang baik, hingga developer profesional yang ingin menyempurnakan aplikasi berskala
besar.
Sebagai bonus, ebook ini dilengkapi dengan studi kasus proyek nyata: aplikasi donasi online
yang terintegrasi dengan pembayaran otomatis Midtrans. Anda akan dibimbing melalui setiap
langkah, memahami praktik terbaik dalam proyek nyata yang siap produksi.
Dengan panduan ini, Anda bisa meningkatkan keterampilan Laravel dan memastikan aplikasi
yang Anda bangun lebih profesional, aman, dan scalable!
5
Hak Cipta & Ketentuan Penggunaan
• Email: codingtengahmalam@gmail.com
• Instagram: (codingtengahmalam?)
6
Changelogs
Berikut adalah daftar perubahan dan pembaruan isi eBook ini dari waktu ke waktu. Kami
berkomitmen untuk terus memperbarui konten sesuai perkembangan Laravel dan best practice
terbaru.
• Penambahan bab baru dengan tujuan membuat Laravel yang lebih modular dan aman
• Versi awal dari eBook ini dirilis dengan fokus pada Fundamental Best Practices Laravel
• Menyediakan panduan lengkap tentang penggunaan Laravel, mulai dari instalasi hingga
penerapan best practices dalam pengembangan aplikasi
• Menyertakan contoh kode dan penjelasan mendetail untuk setiap topik yang dibahas
• Memperkenalkan konsep-konsep dasar Laravel seperti routing, middleware, dan pengelo-
laan database
7
Aturan Penamaan Laravel
Laravel adalah framework yang telah di desain sedermikian rupa untuk membuat developer
menjadi lebih produktif, efektif dan membuat kita hanya fokus untuk mengembangkan produk
saja.
Untuk meningkatkan produktivitas hal yang harus dilakukan adalah menulis kode sesuai den-
gan standar Laravel. baik bekerja secara tim maupun individu, mengikuti standar kode meru-
pakan investasi.
Mungkin sebagian developer yang belum terbiasa akan merasa mengikuti standar malah mem-
persulit proses development. Namun percayalah, ketika project kamu sudah selesai dan suatu
hari nanti kamu perlu membuka-nya kembali jika kamu tidak mengikuti standar yang ada,
kamu akan membuang banyak waktu.
Selain itu, mengikuti konvensi penamaan Laravel juga meningkatkan keamanan dan performa
aplikasi. Dengan struktur yang konsisten, lebih mudah untuk mendeteksi dan memperbaiki
potensi masalah keamanan. Performa juga dapat ditingkatkan karena kode yang terorganisir
dengan baik lebih mudah dioptimalkan dan di-cache.
Saat ini Laravel menerapkan PSR-12: Extended Coding Style standar ini berisikan
ketentuan yang sangat mendetail mengenai gaya untuk menulis kode PHP.
Berikut ini adalah contoh konversi penamaan yang sesuai dengan standar Laravel
Bahasa
Gunakan bahasa Inggris untuk semua komponen dalam Laravel.
Database - Nama Tabel: Gunakan kata jamak (contoh: donations).
- Nama Kolom: Gunakan snake_case (contoh: short_description).
- Primary Key: Gunakan id sebagai primary key secara default.
Model & Controller - Model: Gunakan kata tunggal (contoh: Donation).
- Controller: Gunakan kata tunggal dengan akhiran Controller (contoh: DonationController).
Method, Variable, dan Route - Method: Gunakan camelCase (contoh: donationPackages).
- Variabel: Gunakan camelCase (contoh: $currentDonation).
- Route:
- Gunakan kata jamak (contoh: Route::resource('donations')).
- Gunakan snake_case dengan notasi dot untuk nama router (contoh: donations.show_package).
8
Relationship dalam Eloquent - hasOne, belongsTo: Gunakan kata tunggal (contoh:
author).
- hasMany, belongsToMany: Gunakan kata jamak (contoh: donations, payments).
Seeder & View - Seeder Gunakan kata tunggal dengan akhiran Seeder (contoh:
DonationSeeder).
- View: Gunakan kebab-case untuk penamaan file (contoh: show-detail-donation.blade.php).
Resource Controller - Gunakan Route::resource('donations', DonationController::class)
hanya jika controller digunakan untuk mengelola resource.
Dan masih banyak lagi konvensi penamaan yang perlu diperhatikan dalam Laravel.
Dengan mengikuti konvensi penamaan yang konsisten seperti yang dijelaskan di atas, pro-
jectmu akan menjadi lebih terstruktur dan mudah dipahami. Hal ini tidak hanya membantu
dalam pemeliharaan kode jangka panjang, tetapi juga memudahkan kolaborasi dengan devel-
oper lain.
9
Konsep DRY (Don’t Repeat Yourself)
Konsep DRY (Don’t Repeat Yourself) dalam pemrograman berarti menghindari pengu-
langan kode atau logika yang sama di berbagai tempat. Tujuannya adalah membuat kode
lebih efisien, mudah dipelihara, dan bebas dari bug.
Dengan menerapkan prinsip DRY, kita bisa mengubah atau memperbaiki logika hanya pada
satu tempat saja, tanpa harus mencari dan mengubah kode yang sama di banyak lokasi.
Konsep DRY juga bisa diterapkan dalam kehidupan sehari-hari untuk meningkatkan efisiensi
dan produktivitas. Salah satu contoh sederhana adalah dalam membuat daftar belanja ming-
guan. Mari kita lihat bagaimana konsep DRY bisa membantu mengorganisir kegiatan rutin
dengan lebih efektif.
Daripada menulis ulang daftar belanja setiap minggu dari awal, kita bisa menyimpan satu
daftar belanja mingguan yang berisi barang-barang kebutuhan rutin, seperti beras, telur, susu,
dan sayuran. Setiap minggu, cukup buka daftar tersebut dan tambahkan atau kurangi barang
sesuai kebutuhan saat itu.
Kebutuhan Pokok
- [ ] Beras – 5 kg
- [ ] Telur – 1 lusin
- [ ] Susu UHT – 3 kotak
- [ ] Minyak goreng – 2 liter
- [ ] Gula pasir – 1 kg
10
Protein
- [ ] Daging ayam – 1 kg
- [ ] Tahu – 10 potong
- [ ] Tempe – 2 papan
Keuntungan: KIta tidak perlu mengulang penulisan barang yang sama berulang kali, se-
hingga menghemat waktu dan memastikan tidak ada barang yang terlewat.
Dalam aplikasi penggalangan dana, kita sering membutuhkan data total donasi yang dita-
mpilkan di berbagai tempat seperti Dashboard, Report, detail donasi, dan riwayat donasi
pengguna. Berikut adalah contoh penerapan dengan dan tanpa konsep DRY:
Tanpa menerapkan konsep DRY
// DashboardController
$totalDonations = Donation::sum('amount');
// ReportController
$totalDonations = Donation::sum('amount');
// UserController
$totalDonations = Donation::where('user_id', $userId)->sum('amount');
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
11
{
$query = self::query();
if ($userId) {
$query->where('user_id', $userId);
}
return $query->sum('amount');
}
}
Maka pada tiap - tiap controller kita cukup memanggil method yang sudah kita buat sebelum-
nya, seperti contoh dibawah ini:
// DashboardController
$totalDonations = Donation::getTotalDonations();
// ReportController
$totalDonations = Donation::getTotalDonations();
// UserController
$totalDonations = Donation::getTotalDonations($userId);
Keuntungan
Dengan menerapkan konsep DRY, kita mendapatkan beberapa keuntungan: 1. Mudah
Dikelola: Perubahan logika hanya perlu dilakukan di satu tempat. 2. Konsisten: Seluruh
bagian aplikasi menggunakan logika yang seragam. 3. Efisien: Menghilangkan pengulangan
kode yang tidak perlu.
Penerapan DRY menjadikan aplikasi lebih modular dan mudah dikembangkan di masa de-
pan.
Selain itu, DRY juga mendorong pengembang untuk berpikir lebih sistematis dalam merancang
solusi, sehingga menghasilkan arsitektur aplikasi yang lebih baik. Dengan menerapkan prinsip
ini secara konsisten, tim pengembang dapat fokus pada fitur-fitur baru daripada menghabiskan
waktu untuk memperbaiki kode yang berulang.
12
Implementasi Gaya Koding SOLID
Salah satu konsep yang sering dipakai dalam pengembangan perangkat lunak adalah SOLID.
Konsep ini pertama kali diperkenalkan oleh Robert C. Martin pada tahun 2000-an lewat
bukunya, “Design Principles and Design Patterns.”. Berikut ini adalah keuntungan jika kita
menggunakan konsep SOLID dalam pengembangan perangkat lunak:
SOLID terdiri dari 4 konsep utama, yaitu Single Responsibility Principle (SRP), Open-Closed
Principle (OCP), Liskov Substitution Principle (LSP), dan Interface Segregation Principle
(ISP). Mari kita bahas satu per satu konsep tersebut.
Setiap class atau fungsi pada kode wajib memiliki satu tanggung jawab dan hanya satu
alasan untuk diubah. Tujuannya adalah meningkatkan kohesi, mengurangi kompleksitas, dan
memudahkan modifikasi. Dengan kata lain, suatu fungsi tidak diperbolehkan mengerjakan
banyak hal,
Sebagai contoh, fungsi yang mendefinisikan struktur data hanya akan diubah saat ada peruba-
han pada struktur data tersebut, sedangkan class/fungsi yang menangani business logic hanya
akan dimodifikasi ketika terjadi perubahan pada business logic.
Di Laravel, kita mengenal Form Request yang, jika diimplementasikan dengan tepat, akan
sesuai dengan konsep SRP. Berikut adalah contoh penerapannya:
// form request
13
'campaign_id' => 'required',
'amount' => 'required|numeric',
'message' => 'nullable|string',
'is_visible' => 'boolean'
];
}
}
// Controller
namespace App\Http\Controllers;
// logic lainnya
}
}
Pada contoh di atas, proses validasi data dipisahkan dari controller dan ditempatkan pada
class terpisah yaitu DonationRequest. Dengan demikian, controller dapat fokus pada penan-
ganan logika bisnis utama, sedangkan validasi data dikelola secara independen. Pemisahan ini
menghasilkan kode yang lebih terorganisir dan mudah dirawat.
Dengan menerapkan SRP, kita juga mendapatkan keuntungan dalam hal pengujian, karena
setiap komponen dapat diuji secara terpisah dan lebih mudah untuk memastikan bahwa setiap
bagian berfungsi sesuai dengan yang diharapkan. Selain itu, ketika ada kebutuhan untuk
mengubah logika validasi, kita hanya perlu fokus pada DonationRequest tanpa khawatir akan
mempengaruhi logika bisnis di controller.
Open/closed principle
Software entities (kelas, modul, fungsi, dll.) sebaiknya terbuka untuk ekstensi tetapi tertutup
untuk modifikasi, kita dapat menambahkan fitur baru tanpa harus mengubah kode yang sudah
ada.
Hal ini membantu kita menghindari bug yang mungkin muncul akibat modifikasi kode yang
telah berjalan. Memodifikasi kode yang sudah ada berisiko menimbulkan bug di production.
Selain itu, kita harus melakukan testing ulang pada kode lama—sesuatu yang seharusnya tidak
14
perlu jika menerapkan Open-closed Principle. Prinsip ini mendorong kita untuk menulis kode
yang modular.
Contoh kasus penerapan konsep OCP, perhatikan kode dibawah ini
$donation = Donation::create([
'campaign_id' => $campaign->id,
'user_id' => auth()->id(),
'amount' => $request->amount,
'message' => $request->message,
'is_visible' => $request->is_visible,
'campaign_detail' => json_encode($campaign),
'status' => Donation::STATUS_PENDING,
]);
$donation->update([
'payment_link' => $snapLink->redirect_url,
'payment_detail' => json_encode($snapLink)
]);
return response()->json([
'redirect_url' => $snapLink->redirect_url
]);
}
Kode di atas menangani donasi untuk campaign dengan pembayaran melalui Midtrans. Na-
mun, kode ini tidak mengikuti Open/Closed Principle (OCP) karena hanya mendukung
satu metode pembayaran. Ketika kita ingin menambahkan metode pembayaran baru seperti
PayPal atau Manual Payment, kita terpaksa mengubah kode yang sudah ada.
Penerapan OCP
Agar lebih fleksibel, dan mengikuti konsep OCP, kita bisa memisahkan logika pembayaran
menggunakan Polymorphism dan Dependency Injection.
Buat Interface untuk Pembayaran
15
interface PaymentGatewayInterface {
public function getPaymentLink(Donation $donation);
}
// Midtrans payment
class MidtransGateway implements PaymentGatewayInterface {
public function getPaymentLink(Donation $donation) {
$midtransSnapClient = new MidtransSnap($donation);
return $midtransSnapClient->getSnapLink()->redirect_url;
}
}
// Paypal payment
class PaypalGateway implements PaymentGatewayInterface {
public function getPaymentLink(Donation $donation) {
// integrasi paypay
return "https://paypal.com/checkout?...."
}
}
$campaign = Campaign::findOrFail($request->campaign_id);
$donation = Donation::create([
'campaign_id' => $campaign->id,
'user_id' => auth()->id(),
16
'amount' => $request->amount,
'message' => $request->message,
'is_visible' => $request->is_visible,
'campaign_detail' => json_encode($campaign),
'status' => Donation::STATUS_PENDING,
]);
$donation->update([
'payment_link' => $paymentLink,
'payment_detail' => json_encode(['redirect_url' => $paymentLink ])
]);
return response()->json([
'redirect_url' => $paymentLink
]);
}
Dengan implementasi ini, fungsi donateCampaign telah menerapkan konsep Open/closed prin-
ciple dengan baik. Ketika ada kebutuhan menambah payment gateway baru di masa depan,
kita hanya perlu membuat class baru yang mengimplementasikan interface yang sudah ada
dan menambahkan payment method-nya.
Konsep ini berkaitan dengan inheritance dalam pemrograman. LSP menyatakan bahwa ketika
suatu class mewarisi class induk (baik interface maupun class lainnya), class turunan tersebut
harus dapat berfungsi dengan benar tanpa mengubah perilaku yang sudah ada. Mari kita
lihat contoh implementasi LSP berikut.
17
Sebagai contoh, kita memiliki interface PaymentGatewayInterface yang telah kita buat se-
belumnya. Setiap class yang mengimplementasikan interface ini (MidtransGateway, Paypal-
Gateway, dan ManualPaymentGateway) dapat saling menggantikan tanpa mengganggu fung-
sionalitas sistem.
Namun kemudian kita akan menambahkan metode “Donasi Gratis”, dimana donasi tidak
memerlukan pembayaran sehingga tidak mengembalikan link pembayaran, contohnya seperti
dibawah ini
// interface
interface PaymentGatewayInterface {
public function getPaymentLink(Donation $donation);
}
interface DirectConfirmationPaymentInterface {
public function confirmPayment(Donation $donation);
}
18
return "https://midtrans.com/pay/{$donation->id}";
}
}
Maka kita akan menyesuaikan fungsi donateCampaign menjadi seperti dibawah ini
$paymentMethods = [
'midtrans' => new MidtransPayment(),
'paypal' => new PayPalPayment(),
'free_donation' => new FreeDonationPayment(),
];
if (!isset($paymentMethods[$request->payment_method])) {
throw new \Exception("Metode pembayaran tidak didukung");
}
$paymentMethod = $paymentMethods[$request->payment_method];
19
// ...
Dengen begini tidak ada error saat menganti metode pembayaran karena FreeDonation tidak
lagi dipaksa menggunakan sistem yang salah, selain itu kita bisa menambah metode pemba-
yaran lain tanpa mengubah kode utama.
Dalam bahasa inggris segregation memiliki arti keeping things separated. jika dikaitkan dengan
Interface segregation principle memiliki arti pemisahan interface.
Dalam pembuatan interface lebih baik membuat banyak interface dengan fungsi yang spesifik,
hal ini lebih baik daripada membuat satu interface dengan fungsi yang tidak spesifik. Tujuan
dari pemisahan interface adalah untuk tidak memaksa client menggunakan kode yang tidak
diperlukan.
Misalnya, kita punya satu interface besar untuk semua jenis pembayaran:
interface PaymentGatewayInterface {
public function getPaymentLink(Donation $donation);
public function refund(Donation $donation);
}
// implementasi
20
public function refund(Donation $donation) {
// Tidak mungkin ada refund untuk donasi gratis
}
}
interface PaymentGatewayInterface {
public function getPaymentLink(Donation $donation);
}
interface RefundablePaymentInterface {
public function refund(Donation $donation);
}
interface DirectConfirmationPaymentInterface {
public function confirmPayment(Donation $donation);
}
21
public function refund(Donation $donation) {
return "Refund diproses melalui PayPal untuk donasi ID: {$donation->id}";
}
}
Sekarang kita telah menerapkan Interface Segregation Principle (ISP) dengan baik, dengan
detail sebagai berikut:
22
Mutator dan Accessor untuk Format Tanggal
Seringkali kita menyimpan data waktu di dalam database, misal kita punya tabel donations,
akan ada kolom payment_at, confirmed_at dan yang lainnya. baiknya dalam menyimpan
data waktu kita hanya perlu untuk menyimpan data tersebut sesuai dengan standar waktu
yang ada dalam laravel.
Standar waktu ini biasanya menggunakan format ISO 8601 (YYYY-MM-DD HH:MM:SS). Den-
gan menyimpan data dalam format standar, kita dapat dengan mudah memanipulasi dan
menampilkan tanggal sesuai kebutuhan menggunakan fitur Accessors dan Mutators di Laravel.
Ini memungkinkan kita untuk mengubah format tanggal saat mengambil atau menyimpan data
tanpa mengubah struktur database.
Berikut adalah contoh penggunaan Accessors dan Mutators untuk mengelola format tanggal:
// Model
protected $casts = [
'payment_at' => 'datetime',
];
/**
* Accessor: Formatkan kolom payment_at saat membaca
* (jika ingin dibaca dalam ISO 8601)
*/
public function getPaymentAtAttribute($value)
{
return Carbon::parse($value)->toIso8601String();
}
/**
* Mutator: Ubah nilai payment_at menjadi format ISO 8601 sebelum disimpan
*/
public function setPaymentAtAttribute($value)
{
$this->attributes['payment_at'] = Carbon::parse($value)->toIso8601String();
}
// View
23
{{ $object->payment_at->toDateString() }}
{{ $object->payment_at }}
Dengan menggunakan Accessors dan Mutators, kita dapat dengan mudah memanipulasi for-
mat tanggal tanpa mengubah data asli di database. Ini memberikan fleksibilitas dalam
menampilkan tanggal sesuai kebutuhan aplikasi, seperti format yang berbeda untuk tampi-
lan user dan format standar untuk penyimpanan atau perhitungan.
24
Menggunakan Mass Assignment
Mass Assignment memungkinkan kita mengisi beberapa atribut model sekaligus dalam satu
langkah dengan menggunakan array.
Metode ini jauh lebih efisien daripada mengisi atribut satu per satu.
Dengan Mass Assignment, kita dapat mengirim array data ke model lalu Laravel akan secara
otomatis menetapkan nilai-nilai tersebut ke atribut yang sesuai. Ini sangat berguna ketika
bekerja dengan form input yang memiliki banyak field. Namun, penting untuk berhati-hati
dan menggunakan fitur ini dengan bijak untuk menghindari masalah keamanan.
Untuk menggunakan Mass Assignment dengan aman, Laravel menyediakan $fillable dan
$guarded pada model.
Dengan mengonfigurasi salah satu dari keduanya, kita dapat mencegah pengisian atribut
yang tidak diinginkan dan meningkatkan keamanan aplikasi. Selain itu, selalu validasi in-
put pengguna sebelum menggunakannya dalam Mass Assignment untuk menambah lapisan
keamanan.
Berikut ini adalah contoh dalam menggunakan dan tanpa menggunakan
25
$user->password = bcrypt('secret');
$user->save();
Selain itu kita juga bisa melakukan mengkombinasikan-nya dengan mengembalikan hasil dari
validasi request, seperti contoh dibawah ini
$validatedData = $request->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users,email',
'password' => 'required|string|min:8',
]);
User::create([
...$validatedData,
'password' => bcrypt($validatedData['password']),
]);
Dengan menggunakan Mass Assignment yang dikombinasikan dengan validasi request, kita
dapat memastikan data yang masuk sudah tervalidasi sebelum disimpan ke database. Hal ini
tidak hanya membuat kode lebih ringkas, tetapi juga meningkatkan
keamanan dan maintainability aplikasi. Pendekatan ini sangat direkomendasikan untuk
menangani input form dalam aplikasi Laravel.
26
Hindari Penggunaan Magic String
Magic string adalah penulisan nilai string secara langsung dalam kode program tanpa mendefin-
isikannya di satu tempat terpusat.
Praktik ini merupakan pendekatan yang tidak disarankan dalam pengembangan perangkat
lunak karena dapat menyebabkan berbagai masalah dalam pemeliharaan dan pengembangan
kode. Ketika nilai string ditulis secara langsung di berbagai tempat dalam kode, hal ini dapat
membuat kode menjadi sulit untuk dikelola dan rentan terhadap kesalahan. Contoh magic
string sebagai berikut:
class User
{
private string $type;
Penggunaan magic string baiknya dihindari, karena memiliki banyak kekurangan, diantaranya
adalah sebagai berikut:
Rentan terhadap typo
String yang di-hardcode tidak memiliki validasi dari compiler atau IDE. Jika typo kesalahan
ini hanya akan terdeteksi saat runtime, yang bisa menyebabkan bug yang sulit dilacak.
Sulit di pelihara (Maintainability)
27
Jika string digunakan pada banyak tempat, maka ketika ada perubahan pada string tersebut
memerluklan perubahan juga pada semua tempat yang menggunakannya, dengan begitu dapat
meningkatkan resiko kesalahan dan membutuhkan waktu untuk maintain hal tesebut.
Contohnya terdapat validasi pada variable $status, yang sebelumnya adalah ‘normal’
menjadi ‘regular’ maka harus mencari dan menggubah semua string “normal” menjadi
“regular”
Sulit dipahami tool Editor
Dengan menggunakan magic string, Tool Editor code seperti PHPStrom, VScode, dan lainnya
sulti untuk memahami project yang sedang dibuka, hal ini menjadikan tidak bisa menjalankan
feature refactoring, automcomplate dan pengecekan tipe tipe data
Konteks tidak Jelas
String yang ditulis hardcode tidak memberkan konteks yang jelas, pembaca kode harus berfikir
dan menebak apa maksud dari string tersebut.
Contohnya jika kita diberikan “nomal”,”regular”,”ordinary” atau “expected” tanpa ada kon-
teks yang jelas hal ini sangat membingungkan
Untuk menghindari penggunaan magic string, kita dapat menggunakan beberapa pendekatan
berikut:
Menggunakan Konstanta
Definisikan string yang sering digunakan sebagai konstanta dalam class:
class User
{
private const TYPE_NORMAL = 'normal';
private string $type;
28
}
}
Menggunakan Enum
Gunakan enum untuk membatasi nilai yang valid:
class User
{
private UserType $type;
class User
{
29
private string $type;
• IDE dapat memberikan autocompletion yang akurat dan cepat, membantu developer
menulis kode dengan lebih efisien dan mengurangi kesalahan pengetikan
• Compiler memiliki kemampuan untuk mendeteksi kesalahan pengetikan secara otomatis
pada tahap kompilasi, sehingga mencegah bug sebelum kode dijalankan
• Proses refactoring menjadi jauh lebih mudah dan aman karena semua nilai string terpusat
di satu lokasi, memungkinkan perubahan dapat dilakukan secara konsisten di seluruh
aplikasi
• Kode menjadi lebih self-documenting dan mudah dipahami oleh developer lain, karena
penggunaan konstanta dan enum memberikan konteks yang jelas tentang maksud dan
tujuan dari setiap nilai
30
Kirimkan Tugas Berat Ke Background
31
Pengenalan Laravel Queue
Laravel Queue memungkinkan kita untuk mengirimkan eksekusi tugas yang berat ke back-
ground process, sehingga aplikasi tetap berjalan lancar sambil memproses pekerjaan secara
asinkron.
Ĺ Note
Background process adalah proses yang berjalan di belakang layar tanpa mengganggu
eksekusi utama aplikasi.
Dalam pengembangan aplikasi Laravel skala besar, kita sering membuat fitur yang mem-
butuhkan waktu pemrosesan yang lama, misalnya pengiriman email, pemrosesan file, atau
integrasi dengan layanan pihak ketiga. Jika dijalankan secara langsung, operasi-operasi ini
bisa membuat aplikasi kita terasa lambat bagi pengguna.
Jika kita memiliki fitur untuk melakukan pembayaran lalu mengirimkan email mengenai status
pembayaran. Tanpa queue, proses ini akan membuat server harus menunggu proses pengiriman
email hingga selesai. Dengan queue, kita bisa memindahkan proses kirim email ke background,
dibawah ini adalah ilustrasi dari penggunaan Queue.
Jadi dari sisi user akan mendapatkan respon yang cepat karena server tidak perlu menunggu
proses pengiriman email selesai. Queue akan menangani tugas pengiriman email di background
sementara user bisa melanjutkan aktivitas lainnya di aplikasi.
32
Driver Queue
Laravel mendukung beberapa driver untuk menjalankan queue diantaranya adalah database,
Redis, Amazon SQS, dan Beanstalkd. Masing-masing driver memiliki kelebihan dan karakter-
istik yang berbeda.
Database adalah pilihan paling sederhana karena tidak memerlukan service tambahan, Redis
menawarkan performa tinggi dengan in-memory processing, sementara Amazon SQS cocok
untuk aplikasi yang berjalan di AWS.
Implementasi
Contoh kali ini ada pada fitur pembayaran donasi, dimana setelah user melakukan pemba-
yaran, sistem akan mengirimkan email notifikasi dan mengupdate status pembayaran. Untuk
mengoptimalkan proses ini, kita akan menggunakan queue untuk menangani pengiriman email
di background. Dengan begitu, user bisa langsung mendapatkan respons sukses pembayaran
tanpa harus menunggu email terkirim.
Untuk membuat job baru di Laravel, kita bisa menggunakan perintah artisan:
Perintah ini akan membuat class job baru di folder app/Jobs. Job class ini akan berisi logika
untuk mengirim email notifikasi pembayaran.
Setelah job dibuat, kita perlu mengimplementasikan logika pengiriman email di dalam method
handle(). Method ini akan dijalankan secara otomatis ketika job diproses oleh queue worker.
Berikut adalah contoh implementasi job untuk mengirim email notifikasi pembayaran:
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
33
protected $payment;
Pada kode diatas kita melakukan implementasi dari berbagai macam fungsi yang ada dalam
laravel, diantaranya adalah
ShouldQueue
ShouldQueue adalah interface yang menandakan bahwa job ini harus dijalankan dalam
queue.
InteractsWithQueue
InteractsWithQueue adalah trait yang menyediakan metode untuk berinteraksi dengan an-
trian, seperti:
Queueable
Queueable adalah trait untuk membuat antrian yang fleksibel seperti:
Setelah membuat job class, kita bisa menjalankan job tersebut dari controller atau bagian lain
aplikasi dengan cara:
34
SendPaymentNotification::dispatch($payment);
Secara otomatis, proses ini akan berjalan di background sehingga tidak menghambat respons
aplikasi ke user. Diagram di bawah ini mengilustrasikan bagaimana flow queue bekerja dalam
memproses job pengiriman email notifikasi pembayaran.
Untuk mempermudah memahami proses penggunaan Queue anda dapat melihat diagram
dibawah ini.
Dari diagram tersebut, kita dapat melihat bahwa ketika sebuah job dikirim ke queue, queue
worker akan memproses job tersebut secara asinkron. Job akan diambil dari queue satu per
35
satu, dieksekusi, dan hasilnya akan dicatat. Jika terjadi kegagalan, job dapat diulang sesuai
dengan konfigurasi yang telah ditentukan.
Untuk memproses job dalam queue, kita perlu menjalankan queue worker. Queue worker
adalah proses yang berjalan di background dan terus memonitor queue untuk mengeksekusi
job yang masuk. Untuk menjalankan queue worker, gunakan perintah:
Ĺ Note
Supervisor adalah proses manajer yang digunakan untuk menjaga queue worker tetap
berjalan secara otomatis.
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /path/to/artisan queue:work --sleep=3 --tries=3
autostart=true
autorestart=true
user=forge
numprocs=8
redirect_stderr=true
stdout_logfile=/path/to/worker.log
Dengan menggunakan queue aplikasi yang kita buat bisa lebih responsif memberikan response
yang diberikan kepada user. Proses-proses berat seperti pengiriman email atau pemrosesan
file dapat berjalan di background tanpa mengganggu pengalaman pengguna. Hal ini sangat
penting terutama untuk aplikasi yang memiliki traffic tinggi.
36
Laravel Repository Pattern
Design patternadalah suatu metode yang digunakan untuk menyelesaikan permasalahan yang
sering terjadi dan biasanya memiliki suatu pola dalam menyelesaikan masalah.Design Pat-
terndapat mempercepat pengembangan suatu perangkat lunak. Salah satu dariDesign Pat-
ternyang paling sering digunakan adalahRepository Pattern.
Secara singkatnya Repository Pattern adalah suatu pendekatan arsitektur perangkat lunak
yang memisahkan antara Business Logic layer dengan Data Access Logic layer. Pemisahan ini
bertujuan untuk membuat kode lebih terstruktur, mudah dikelola, dan mudah diuji.
Dengan menggunakan repository pattern, business logic layer tidak perlu mengetahui detail
implementasi tentang sumber dan tujuan data. Ini berarti lapisan bisnis tidak perlu tahu
apakah data berasal dari database SQL, NoSQL, API eksternal, atau sistem penyimpanan
lainnya. Business logic layer hanya bertugas mengimplementasikan proses bisnis dan menye-
lesaikan masalah yang ada sesuai dengan kebutuhan aplikasi.
Pendekatan ini memberikan beberapa keuntungan penting: meningkatkan maintainability
kode, memudahkan unit testing, dan membuat kode lebih fleksibel terhadap perubahan sum-
ber data di masa depan. Selain itu, dengan memisahkan kedua lapisan tersebut, developer
dapat bekerja secara paralel pada masing-masing lapisan tanpa saling mengganggu.
37
Figure 1: ilustrasi penggunaan repository pattern
Dalam implementasinya, Repository Pattern biasanya terdiri dari interface yang mendefin-
isikan operasi-operasi dasar untuk mengakses data (seperti Create, Read, Update, Delete)
dan satu atau lebih implementasi konkret dari interface tersebut. Hal ini memungkinkan
untuk mengganti implementasi repository tanpa mempengaruhi kode yang menggunakannya.
Dengan pendekatan ini, kita dapat dengan mudah mengganti sumber data atau menambahkan
fungsionalitas baru tanpa perlu mengubah logika bisnis yang ada.
Pada contoh implementasi kali ini kita akan menggunakan tabel campaigns yang isinya adalah
informasi iklan donasi yang ada pada sistem donasi online.
Buat Folder Khusus
Langkah pertama adalah kita membuat folder Repository folder ini akan menyimpan berba-
gai repository yang akan digunakan, folder ini berada didalam folder app, untuk lebih jelas
perhatikan tree folder berikut ini
app
����Console
����Exceptions
����Http
� ����Controllers
� ����Middleware
38
����Models
����Providers
����Repository --> Folder untuk menyimpan Repository
� ����Campaign
����Utils
Buat Interface
Untuk memisahkan kode menjadi komponen yang independen (code-decoupling), kita perlu
membuat sebuah interface. Interface ini akan diimplementasikan oleh kelas-kelas yang mem-
butuhkan repository pattern. Interface menjadi kontrak bagi child class-nya yang memberikan
keleluasaan dalam pemilihan mekanisme Data Access Logic.
<?php
namespace App\Repository\Campaign;
use Illuminate\Database\Eloquent\Collection;
interface CampaignRepositoryInterface
{
public function getAll();
public function findById(int $id);
public function create(array $data);
public function update(int $id, array $data);
public function delete(int $id): bool;
}
Implementasi Interface
39
<?php
namespace App\Repository\Campaign;
Implementasi Controller
40
<?php
namespace App\Http\Controllers;
use App\Repository\Campaign\CampaignRepositoryInterface;
41
Logging dan Monitoring
Bagi developer pemula logging dan monitoring seringkali di lupakan, padahal hal ini meru-
pakan suatu aspek yang penting. dengan ini kita bisa melakukan berbagai tindakan opera-
sional yang bisa membuat aplikasi berjalan sesuai dengan fungsinya.
Aplikasi yang telah kita deploy ke production menunjukan penurunan performa, kasusnya
adalah ketika mengambil data perlu loading time yang tinggi.
Maka ketika ada masalah tersebut kita bisa melakukan analisis log dan memerika apa yang
sedang terjadi karena akan ada banyak kemungkinan yang menyebabkan aplikasi kita men-
galami penurunan performa, dari hasil logging dan monitoring yang telah dilakukan kita bisa
menentukan aksi selanjutnya yang lebih cepat dan terarah.
Logging
Proses merekam aktivitas yang terjadi dalam suatu aplikasi dan menyimpannya ke dalam
bentuk file atau sistem penyimpanan lainnya, biasanya disimpan dalam bentuk JSON atau
dalam bentuk file .log lengkap dengan timestamp kejadian. Logging dapat digunakan untuk
melakukan investigasi jika terjadi anomali pada aplikasi yang sedang berjalan.
Pada Laravel secara default semua log akan ditulis pada /project/storage/logs/laravel.log
aktifitas yang di tulis adalah adalah ketika terjadi internal server error dan memberikan stack
trace error tersebut. contohnya seperrti dibawa ini:
#0 project/php/beramal/vendor/laravel/framework/src/Illuminate/Database/Connection.php(767):
Illuminate\\Database\\Connection-> .... amework/src/Illuminate/Database/Connection.php(385):
Illuminate\\Database\\Connection->select()
#\
42
Informasi tersebut dapat kita gunakan untuk melakukan tindakan lanjutan seperti melakukan
bugfixing.
Monitoring
Proses mengamati kondisi aplikasi yang berjalan secara realtime atau berkala, untuk memas-
tikan aplikasi berjalan normal dan mendetaksi secara dini jika terjadi anomali. Proses mon-
itoring biasanya menampilkan data dalam bentuk metrik, grafik atau dashboard contohnya
seperti dibawah ini:
Laravel menyediakan berbagai fitur logging yang dapat digunakan untuk mencatat aktivitas
aplikasi. Secara default, Laravel menggunakan library Monolog yang menyediakan berbagai
channel logging seperti single, daily, slack, dan lainnya. Konfigurasi logging dapat diatur
melalui file config/logging.php.
43
Kita dapat mengatur level logging sesuai kebutuhan seperti debug, info, warning, error, critical,
dan alert. Setiap level memiliki tingkat kepentingan yang berbeda dan dapat dikonfigurasi
untuk diarahkan ke channel yang berbeda. Sebagai contoh, kita bisa mengirim error logs ke
Slack untuk notifikasi tim, sementara debug logs disimpan dalam file lokal.
Berikut adalah beberapa contoh penggunaan level logging di Laravel:
Log::emergency($message);
Log::alert($message);
Log::critical($message);
Log::error($message);
Log::warning($message);
Log::notice($message);
Log::info($message);
Log::debug($message);
Setiap level logging memiliki fungsinya masing-masing dan sebaiknya digunakan sesuai dengan
konteks dan tingkat urgensinya.
Best practice logging
Berikut adalah beberapa Best practice dalam menerapkan logging di aplikasi Laravel:
1. Gunakan log level yang sesuai - pastikan menggunakan level yang tepat sesuai dengan
tingkat kepentingan informasi
2. Struktur log yang konsisten - format log harus konsisten dan mudah dibaca, idealnya
menggunakan format JSON
3. Rotasi log file - terapkan rotasi log untuk menghindari file log yang terlalu besar dan
memakan storage, pada .env laravel set configurasi berikut ini APP_LOG=daily
4. Informasi kontekstual - sertakan informasi yang membantu debug seperti timestamp,
user ID, request ID
5. Hindari data sensitif - jangan mencatat informasi sensitif seperti password atau token
dalam log
{
"timestamp": "2025-02-23T12:34:56Z",
"level": "error",
"message": "Database connection failed",
"context": {
"exception": {
"class": "PDOException",
"message": "SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost'",
44
"file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php"
"line": 150
},
"request": {
"method": "POST",
"url": "/login",
"ip": "192.168.1.1",
"user_id": 12345
}
}
}
Ĺ Note
Untuk memudahkan melihat isi log yang dihasilkan oleh aplikasi, kita bisa menggunakan
package opcodesio/log-viewer
Selain itu, penting untuk melakukan monitoring terhadap ukuran log file dan mengimplemen-
tasikan strategi pembersihan log yang efektif. Log yang terlalu besar dapat mempengaruhi
performa sistem dan menyulitkan proses analisis.
Untuk mengatasi hal ini, sebaiknya menerapkan strategi rotasi log yang teratur dan menyim-
pan log historis di storage terpisah. Implementasi tools monitoring seperti ELK Stack atau
Graylog juga dapat membantu dalam mengelola dan menganalisis log secara lebih efektif.
Selain itu, penggunaan log rotation dan monitoring tools juga membantu dalam mengop-
timalkan penggunaan storage dan mempermudah proses analisis log. Dengan menerapkan
praktik logging yang baik, developer dapat lebih mudah melakukan troubleshooting dan main-
tenance aplikasi.
Untuk memastikan efektivitas logging, penting juga untuk melakukan review berkala terhadap
log yang dihasilkan dan memastikan bahwa informasi yang dicatat benar-benar berguna untuk
proses debugging dan analisis. Implementasi logging yang baik harus seimbang antara detail
informasi yang dicatat dan overhead yang dihasilkan pada sistem.
Untuk melakukan monitoring aplikasi laravel yang telah kita buat, tersedia banyak tools yang
bisa digunakan, berikut adalah beberapa tools yang sering digunakan untuk melakukan mon-
45
itoring pada aplikasi Laravel. Tools-tools ini memiliki keunggulan masing-masing dan dapat
disesuaikan dengan kebutuhan project yang sedang dikerjakan.
Laravel telescope
Laravel Telescope adalah package debugging yang powerful untuk aplikasi Laravel. Package
ini menyediakan insight mendalam tentang request yang masuk, exception, query database,
queued jobs, mail, notifikasi, cache operations, scheduled tasks, variable dumps dan banyak
lagi. Telescope membantu developer memahami apa yang terjadi di dalam aplikasi secara real-
time dan mempermudah proses debugging. Informasi lebih lengkap dapat klik link berikut
ini.
Health Checkpoint
Health checkpoint adalah fitur yang memungkinkan kita untuk memonitor kesehatan aplikasi
dengan melakukan pengecekan terhadap komponen-komponen kritis seperti koneksi database,
cache, queue, dan layanan eksternal. Dengan mengimplementasikan health checks, kita dapat
mendeteksi masalah sebelum berdampak pada pengguna.
Kita bisa membuat sendiri atau menggunakan package seperti spatie/laravel-health yang
dapat digunakan untuk mengimplementasikan health checks dengan mudah.
Application Performance Monitoring
Beberapa tools APM (Application Performance Monitoring) populer yang dapat digunakan
untuk memonitor aplikasi Laravel, contohnya Sentry, New Relic, Datadog, dan Scout APM.
Ĺ Note
Gunakan Sentry unutk tools APM yang ramah pemula, dan terdapat free tier untuk
belajar.
Tools ini menyediakan insight mendalam tentang performa aplikasi, memungkinkan developer
untuk mengidentifikasi bottleneck, melacak response time, dan menganalisis penggunaan re-
sources.
Dengan menggunakan APM tools, tim dapat proaktif mendeteksi dan menyelesaikan masalah
performa sebelum mempengaruhi pengalaman pengguna.
46
penting dan relevan untuk debugging dan monitoring. Pastikan untuk menyaring data yang
dicatat agar log tetap ringkas dan bermakna.
Tidak peduli log level
Menggunakan log level yang tidak tepat atau mengabaikan penggunaan level yang berbeda
dapat menyebabkan kesulitan dalam mengidentifikasi dan memprioritaskan masalah. Penting
untuk memahami kapan menggunakan level debug, info, warning, atau error sesuai dengan
konteksnya. Penggunaan log level yang tepat membantu dalam proses troubleshooting dan
memudahkan dalam memfilter log berdasarkan tingkat kepentingannya.
Tidak manage file log
Jika memiliki storage yang terbatas, file log bisa menjadi salah satu yang memakan banyak
storage, maka dari itu perlu dilakukan hapus seara berkala dalam kurun waktu tertentu. Hal
ini bisa menghemat storage dan memudahkan tools melakukan analisis file log.
47
N+1 Query Problem
Secara sederhana n+1 adalah problem yang seringkali terjadi ketika aplikasi melakukan query
ke database, problemnya terletak pada jumlah query yang berlebihan, sehingga menurunkan
performa dari aplikasi yang sedang berjalan.
N+1 Sering terjadi ketika aplikasi yang kita buat menggunakan ORM, pada konteks Laravel
N+1 sering terjadi ketika kita menuliskan query dengan menggunakan Elaqunent ORM
Contoh Masalah
Pada aplikasi yang kita buat memiliki tabel Campaigns dan Comments, setiap campaign bisa
memiliki banyak comments, pada suatu halaman kita akan menampikan data campaigns dan
comments yang terkait. Maka seringkali melakukan query dengan menggunakan syntax seperti
dibawah ini
Pada query pertama adalah SELECT * FROM campaigns WHERE status = ‘active’ lalu un-
tuk setiap campaigns aplikasi melakukan query kembali untuk menampilkan data comments
yang terkait dengan campaign, query yang dilakukan adalah SELECT * FROM comments WHERE
campaign_id = ?
Misalknya terdapat data 100 Campaign maka query yang dilakukan adalah 101 Query, dengan
penjelasan
48
• Query utama: 1 untuk menggambil data Campaign dan menyimpannya pada variable
$campaigns
• Query tambahan: 100 masing - masing untuk mengambil data Commments yang terkait
Untuk memudahkan pemahaman mengenai N+1 Query kamu bisa melihat diaragm dibawah
ini:
49
Figure 1: N+1 Query Problem
50
Solusi utama: Eager Loading
Solusi N+1 Query pada Laravel adalah Eager Loading, dengan menggunakan eager loading
maka seluruh data akan diambil dalam satu query utama. Eager loading memungkinkan kita
untuk mengambil data pada tabel yang saling berhubungan, misalnya tabel Campaigns dan
Comments.
Untuk menerapkan eager loading maka hal yang perlu dilakukan adalah mendefinisikan rela-
tion pada masing - masing model tabel yang saling berhubungan, misalnya:
// campaigns model
class Campaign extends Model
{
public function comments()
{
return $this->hasMany(Comment::class);
}
}
// comments model
class Comment extends Model
{
public function campaign()
{
return $this->belongsTo(Campaign::class);
}
}
Kata kunci utama untuk mengaktifkan eager loading pada tiap query yang dibuat adalah
with() , berikut ini adalah contoh implementasi.
51
1. SELECT * FROM campaigns where status = ‘’active”;
Query ini mengambil data utama campign, misal terdapat 100 active campaigns, maka
akan mendapatkan ID: 1,2,3,4,5 … 100
2. SELECT * FROM comments WHERE campaign_id IN (1, 2, 3, ..., 100);
Query ini akan menggambil semua data komentar untuk 100 campaigns sekaligus, hasil-
nya dalam memory sudah terdapat data 100 campaigns dan semua komentar yang terkait
dengan campaigns
JIka dibandingkan maka berikut ini adalah jumlah query dari masing - masing metode yang
telah kita implementasikan
Setelah ke 2 query dijalankan, Laravel Elaquent akan secara otomatis memetakan ke data
comments ke Campaigns yang sesuai menggunakan campaign_id pada tabel comments. Proses
ini disebut dengan data Hydration
Kita bisa melakukan eager loading pada beberapa relasi sekaligus, ini sangat berguna untuk
tabel yang memiliki relasi lebih dari 1 ke tabel lainnya, misalkan tabel campaigns dengan
tabel comments dan tabel user contoh penulisannya adalah sebagai berikut:
52
$campaigns = Campaign::with(['comments', 'user'])->get();
Seringkali kita ingin mengambil data dari relasi yang berelasi, misal kita ingin menggambil
data author dari tabel comments, maka kita bisa menulis sintax seperti dibawah ini:
$campaigns = Campaign::with('comments.user')->get();
Seringkali kita ingin melakukan eager loading pada suatu relasi dan menambahkan kondisi
pada query yang kita buat, hal ini bisa kita lakukan dengan memberikan array ke method
with() .
Misalnya kita hanya ingin menampilkan Campaign yang memiliki komentar lebih dari 10,
maka kita bisa menggunakan query seperti dibawah ini
$campaigns = Campaigns::where('status','=','active')
->with(['comments' => function (Builder $query) {
$query->count() > 10;
}])->get();
Kesimpulan
Eager Loading sangat berguna untuk melakukan akses data yang berelasi karena memu-
ngkinkan pengambilan data secara efisien dalam jumlah query yang minimal. Dengan teknik
ini, Anda tidak hanya menghemat sumber daya database tetapi juga meningkatkan respon-
sivitas aplikasi secara signifikan Eager Loading wajib dipakai untuk membuat aplikasi lebih
scalable
53
Mempercepat Load Data dengan Caching
Layer
Caching merupakan salah satu metode yang sering kali di lakukan untuk meningkatkan per-
forma aplikasi, cache digunakan sebagai secondary data store untuk menyimpan data yang
sering diakses oleh pengguna, cache menggunakan memori komputer sebagai media untuk
menyimpan data sehingga memiliki kecepatan membaca data yang sangat cepat.
Data yang disimpan dalam cache merupakan data hasil proses yang dinilai memakan biaya
tinggi dalam prosesnya (misal: koneksi ke basis data), atau bisa juga data yang sering di akses
dan jarang ada perubahan.
Laravel memiliki banyak cache driver yang kita bisa gunakan, saat ini kita bisa memiliih
File, Database, Redis, Memcached, Array dan Dynamodb, yang perlu kita lakukan hanyalan
mengubah environtment variable CACHE_DRIVER . Pada bab kali ini kita akan menggunakan
driver Redis sebagai cache Layer.
User akan melakukan request ke salah satu endpoint yang disediakan, kemudian diproses oleh
service yang di tuju, setelah itu service akan menjalankan fungsional yang telah di tentukan,
misal melakukan sanitasi input, selanjutnya melakukan proses query ke basis data, semua
54
proses yang dilakukan memakan waktu kurang lebih selama 250ms, setelah itu akan
mengembalikan hasil ke user.
Jika dilakukan kalkulasi total waktu yang dibutuhkan dari request sampai dengan user respond
adalah 300ms. dengan estimasi 250ms untuk proses query database dan 50ms untuk proses
komputasi.
Jika service di akses hanya puluhan user mungkin tidak akan ada masalah, namun masalah
akan timbul jika ada ratusan user melakukan akses secara bersamaan. Salah satu sekenario
terburuk adalah database mengalami crash karena tidak bisa menangani banyaknya request.
Jika suatu aplikasi memiliki banyak pengguna dan terdapat banyak proses yang berat didalam-
nya maka sudah saat-nya untuk melakukan implementasi caching.
Request pertama yang dilakukan oleh user akan sama seperti tanpa menggunakan cache,
karena kondisi cache yang kosong. Setelahnya hasil akan disimpan dalam Cache untuk di
akses oleh request selanjutnya. Request ke 2 dan seterusnya tidak akan melakukan query ke
database, hal pertama yang dilakukan adalah mencari apakah data yang diminta ada di dalam
Cache, jika ada data akan di ambil dan di kembalikan ke user, jika tidak proses akan berlanjut
dengan melakukan query ke database.
55
Redis
Redis adalah tempat penyimpanan data (database) yang sangat cepat, karena redis menyim-
pan data yang diterima-nya pada RAM komputer bukan di hardisk seperti database biasa.
untuk belajar lebih lanjut kalian bisa mengunjungi Website Redis
• Cepat banget – Karena Redis nyimpen data langsung di RAM, kecepatan read/write-
nya jauh di atas database biasa atau file.
• Support struktur data kompleks – Redis bukan cuma nyimpen string, dia bisa
simpen list, set, hash, sorted set, dan lain-lain. Jadi kamu bisa simpen data kayak kamu
coding aja.
• Atomic operation – Operasi di Redis bisa dijalankan secara atomik, jadi aman buat
proses paralel.
• Support pub/sub – Redis bisa dipakai buat real-time communication (kayak notifikasi
atau chat) lewat publish/subscribe.
Di aplikasi donasi online yang kita gunakan sebagai studi kasus terdapat halaman
menampilkan detail dari sebuah program donasi tertentu, pada halaman tersebut
ada banyak informasi seperti:
• Judul donasi
• Deskripsi lengkap
• Jumlah donasi yang sudah terkumpul
• Riwayat donatur
• Target donasi
• Progress bar, dll.
Nah, data ini biasanya diambil dari beberapa tabel di database, dan juga perlu ngitung to-
tal donasi atau jumlah donatur dari tabel yang datanya sudah besar banget. Karena harus
ngambil dan ngolah banyak data, maka proses ini bisa jadi lambat, terutama kalau banyak
pengguna buka detail donasi yang sama secara bersamaan.
56
Implementasi Cache Donasi Online
Setelah kita tau problemnya sekarang kita akan melakukan caching pada data yang akan
ditampilkan kepada user di halaman detail donasi, berikut ini adalah ilustrasi alur proses
bisnis dari kode yang akan kita buat.
Dapat kita lihat kertika user melakukan request ke server untuk ditampilkan data detail
donasi, maka server akan melakukan pemeriksaan terlebih dahulu ke Redis/Cache, jika tidak
ditemukan data yang dimaksud maka server akan melakukan query ke database, setelah men-
dapatkan data yang dimaksud data tersebut akan di simpan dalam cache dan kemudian akan
diberikan kembali ke user.
Jika diagram diatas di konversikan menjadi kode pada controller, maka akan menghasilkan
seperti dibawah ini.
use Illuminate\Support\Facades\Cache;
use App\Models\Donation;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;
57
// Ambil data utama donasi + kategori
$donation = Donation::with('category')
->where('slug', $slug)
->firstOrFail();
// Rata-rata donasi
$averageDonation = $donation->donors()->avg('amount');
58
];
});
Dapat kita lihat pada kode diatas kita melakukan import classs Cache use Illuminate\Support\Facades\Cache
. selain itu kita juga menggunakan beberapa fungsi lain seperti
Syntax Description
$cacheKey = Untuk membuat cache key berdasarkan slug
"donation_detail_{$slug}"; donasi. Ini penting supaya data cache tiap
donasi tidak bentrok.
Cache::remember($cacheKey, Cek apakah data sudah ada di cache. Kalau
now()->addMinutes(10), function () belum, jalankan query di dalam closure, lalu
use ($slug) { ... }); simpan hasilnya ke cache Redis selama 10
menit.
now()->addMinutes(10) Menentukan waktu kedaluwarsa cache
(dalam contoh ini: 10 menit). Setelah itu,
cache otomatis dianggap kadaluarsa dan
akan dibuat ulang.
Bagaimana jika sebelum waktu-nya kedaluarsa sumber data yang asli sudah berubah, maka
user akan tetap melihat data lama dari cache, bukan data terbaru dari database. Ini adalah
risiko utama saat menggunakan cache, terutama pada data yang sering berubah.
Maka dari itu hal yang bisa dilakukan adalah menghapus Cache ketika data berubah, hal
ini bisa dilakukan dengan melakukan implementasi pada fungsi yang mengubah data Donasi,
misalnya:
Dengan begitu, ketika ada request untuk menampilkan kembali data, sistem akan mengambil
data terbaru dari database dan menyimpannya kembali ke dalam cache yang baru. Pendekatan
59
ini membantu menjaga konsistensi data dan mencegah tampilan data lama akibat cache yang
tidak diperbarui.
60
Menggunakan Migrations dan Seeder secara
Maksimal
Latar Belakang
Saya seringkali menemukan project Laravel yang tidak memanfaatkan fitur migrations dengan
maksimal, akibatnya muncul banyak masalah yang seharusnya tidak perlu ada kalau dari awal
sudah menggunakan fitur migrations, masalah yang muncul diantaranya
Proses development, 1). ketika dalam satu tim terdapat banyak developer maka ketika ada
satu saja developer yang menggubah struktur database maka developer lain yang terlibat perlu
mengubah secara di komputer mereka, baik secara manual maupun dengan export-import
schema database. 2). perubahan struktur database menjadi tidak terdokumentasi, sehingga
anggota tim tidak mengetahui alasan kenapa suatu tabel/kolom mengalami perubahan
Proses deployment. Pada tahap ini jika terjadi perubahan pada skema database maka de-
veloper harus melakukan import-export data yang ada di komputer mereka ke server produc-
tion, perilaku seperti ini sangat membahayakan dan rawan membuat aplikasi crash sehingga
menimbulkan downtime.
Maka dari itu penggunakan migration dan seeder sangatlah di rekomendasikan untuk memu-
dahkan proses development sampai dengan proses deployment
Migrations dan seeders adalah 2 fitur penting pada Laravel yang tidak bisa di pisahkan.
Migrations seperti blueprint untuk database tugasnya adalah menentukan struktur tabel dan
kolom dalam aplikasi, dengan migration kita bisa menambah/mengurangi/mengubah stuktur
tabel dan kolom dengan menggunakan syntax php. Selain itu ketika kita tergabung dengan
suatu tim kita bisa sync stuktur database antar anggota dengan mudah cukup menjalankan
Seeder fungsinya untuk mengisi data kedalam database, biasanya untuk input data dummy
atau data awal aplikasi, misal kita butuh data 100 user admin di aplikasi dengan seeders kita
bisa input data tersebut dengan mudah di aplikasi
Perbedaan Migration dan seeders
61
Migration fokus ke bentuk dan struktur database—kayak bikin tabel, nambah kolom, atau
hapus kolom. Seeder fokus ke isinya, alias ngisi tabel itu dengan data. Jadi gampangnya,
migration = bentuknya, seeder = isinya. Dua-duanya saling melengkapi, kayak tim yang
solid!
Menggunakan Migration
Untuk membuat migrations kita bisa dengan mudah menggunakan php artisan dengan com-
mand make:migration . setiap command di eksekusi maka akan terbuat file baru pada folder
database/migrations dengan nama file yang berisikan timestamp saat file dibuat.
Contoh pembuatan migration seperti dibawah ini
maka akan terbuat file baru, selanjutnya kita bisa mendefinisikan kolom dan tipe data yang
ada dalam tabel donations, kamu bisa melihat daftar data type yang di dukung Laravel melalui
link berikut https://laravel.com/docs/12.x/migrations#available-column-types
Jika sudah maka idealnya suatu file migrations akan seperti dibawah ini
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
62
$table->dateTime('end_date');
$table->decimal('amount', 15, 2);
$table->foreignId('user_id')->constrained();
$table->softDeletes();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('campaigns');
}
};
Untuk menjalankan migrations kita cukup menggunakan command php artisan migrate
Berikut ini adalah command yang biasa digunakan dalam menggunakan fitur migrations
Perintah Kegunaan
php artisan make:migration Membuat file migration baru. Biasanya
nama_migration digunakan untuk membuat, mengubah, atau
menghapus tabel.
php artisan migrate Menjalankan semua migration yang belum
dijalankan ke database.
php artisan migrate:rollback Mengembalikan (rollback) batch terakhir
dari migration yang sudah dijalankan.
php artisan migrate:reset Mengembalikan semua migration ke awal
(semua migration dibatalkan).
php artisan migrate:refresh Kombinasi dari reset lalu migrate, sering
digunakan untuk reset dan mengisi ulang
database.
php artisan migrate:fresh Menghapus semua tabel dan menjalankan
ulang semua migration dari awal. Cocok
untuk development.
php artisan migrate:status Menampilkan status dari setiap migration,
apakah sudah dijalankan atau belum.
php artisan migrate:install Membuat tabel migrations di database,
yang digunakan Laravel untuk menyimpan
status migration.
63
Perintah Kegunaan
php artisan migrate Menjalankan migration dari file tertentu
--path=path/to/migration.php saja.
php artisan migrate --step Menjalankan migration dengan menyimpan
step-nya, sehingga bisa di-rollback per
langkah.
Menggunakan Seeder
Sebelum menggunakan Seeder pastikan pada Model telah di definisikan $fillable karena
seeder akan menggunakan mass asigments untuk insert data.
protected $fillable = [
'name', 'slug', 'thumbnail', 'description', 'status',
'start_date', 'end_date', 'amount', 'user_id'
];
Membuat file seeder cukup menjalankan command php artisan make:seeder dengan begitu
akan terbuat file baru di folder database/seeders, contohnya kita akan membuat seeder untuk
data Campaign maka kita bisa menjalankan command dibawah ini:
<?php
namespace Database\Seeders;
use App\Models\Campaign;
use App\Models\User;
use Illuminate\Database\Seeder;
use Illuminate\Support\Str;
64
public function run(): void
{
/// isi dari seeder
}
}
Inti dari file ini ada pada method run() kita bisa menggunakan faker untuk mengisi data
dummy, Pada contoh dibawah kita akan memebuat 5 data dummy untuk Campaign dengan
memanfaatkan faker.
<?php
namespace Database\Seeders;
use App\Models\Campaign;
use App\Models\User;
use Illuminate\Database\Seeder;
use Illuminate\Support\Str;
65
}
}
Seringkali kita memiliki banyak file seeder, dari pada menjalakan satu persatu file kita bisa
menggabungkan semua file seeder ke dalam satu file yaitu pada DatabaseSeeder.php di ma-
sukan dalam method call
Ada beberapa command yang bisa di eksekusi untuk menjalankan seeder, berikut ini adalah
command yang biasa digunakan:
66
Dalam membuat migration, sangat penting untuk menggunakan naming convention
yang jelas dan deskriptif. Misalnya, nama seperti create_donations_table atau
add_status_to_users_table akan langsung menggambarkan maksud dari migration.
Hal ini membantu dalam membaca kode, dan juga memudahkan kolaborasi tim dan
proses debugging jika terjadi masalah.
2. Hindari perubahan langsung pada database production tanpa migration
Semua perubahan struktur database sebaiknya dicatat melalui migration supaya bisa
dilacak, dirollback, dan direplikasi dengan konsisten ke environment lain misal staging
atau local development. Langkah ini penting untuk menjaga stabilitas dan integritas
database, serta menghindari error.
3. Gunakan seeder dengan data realistis untuk testing
Saat menggunakan seeder, pastikan untuk mengisi data dengan contoh yang real-
istis. Misalnya, jika membuat data untuk donasi, isi kolom seperti nama donor, jumlah
donasi, dan tanggal donasi dengan nilai yang masuk akal. Data yang realistis membantu
pengujian aplikasi menjadi lebih valid dan mendekati kondisi produksi. Faker bisa digu-
nakan untuk meng-generate data palsu, tapi tetap perlu dikontrol agar hasilnya tetap
natural.
67
Menyusun Routing untuk Project Besar
Laravel merupakan framework yang menerapkan desain arsitektur MVC, yang artinya
memisahkan antara Model (data), View (tampilan), dan Controller (logika aplikasi).
Meskipun routing tidak termasuk dalam definisi formal MVC, perannya routing dalam
Laravel sangat krusial. Routing bertindak sebagai penghubung utama yang memas-
tikan permintaan dari pengguna sampai ke bagian logika yang tepat di dalam
Controller.
Secara praktis, routing bertanggung jawab memetakan alamat URL yang diminta pengguna
dan metode HTTP yang menyertainya (GET, POST, dll.) ke suatu fungsi atau method
spesifik di Controller. Ketika sebuah permintaan diterima oleh aplikasi Laravel, sistem routing
inilah yang pertama kali bekerja untuk menentukan kode mana yang harus dieksekusi sebagai
respons.
Routing bisa dikatakan sebagai jalan yang mengarahkan request pengguna ke controller dan
method yang sesuai, yang selanjutnya method tersebut akan memberikan response sesuai
dengan logika yang ada didalamnya.
Ketika melakukan instalasi Laravel maka kita akan mendapatkan folder router yang didalam-
nya terpadat file-file berikut ini:
• web.php route ini digunakan untuk route aplikasi web pada umumnya, terdapat fitur
stateful dan perlindungan CSRF
• api.php digunakan untuk membuat API yang bersifat stateless, route ini cocok untuk
membuat restfull api yang pembuatan SPA
• channels.php tidak diakses oleh pengguna secara langsung namun file ini digunkan
untuk keperluan modern web application, seperti websocket untuk keperluan realtime
pada suatu webiste
• console.php tempat dimana kita bisa mendefinisikan semua perintah untuk artissan
console, misalnya membuat scheduler
68
Maksimalkan router Laravel
Ketika bekerja dengan project yang besar, fitur router pada Laravel seringkali menjadi
kompleks dan sulit untuk di mantain jika kita tidak mengaturnya dengan baik,
semakin banyak fitur yang kita buat, semakin banyak juga route yang perlu di definisikan.
Seringkali file route menjadi sangat panjang sehingga susah untuk dibaca dan tentunya juga
sangat menyulitkan kalau kita mau menambahkan rute baru.
Maka dari itu saya menerapkan metode di bawah ini dalam proses development proyek besar,
untuk membantu memastikan struktur rute tetap rapi, mudah dipahami, dan efisien dalam
pengelolaan:
Named router adalah aktifitas memberikan nama pada suatu route yang kita definisikan, hal
ini bisa kita lakukan dengan menggunakan method →name(’nama.route’) contoh-nya sebagai
berikut:
Sehingga ketika kita akan melakukan refferensi ke suatu URL bisa menuliskan route(’nama.route’)
pada komponent manapun di aplikasi yang kita buat.
Penggunaan named route memiliki banyak keuntungan, diantaranya adalah:
69
// link ke profile
Untuk operasi Create, Read, Update, dan Delete (CRUD) pada suatu model, saya gunakan
route resource untuk memperpendek penulisan di file web.php. Misalnya saya membuat con-
troller khusus untuk CRUD donation maka saya hanya perlu menuliskan
// web.php
Route::resource('donation', DonationController::class)
Maka secara otomatis akan medefinisikan route dibawah ini dan terhubung dengan metode-
metode yang sesuai pada controller
Jika tanpa menggunakan route resource maka kita perlu menulis semua route dibawah ini,
dapat kita bandingkan berapa line yang bisa dihemat jika menggunakan Route::resource
70
// ditulis secara manual
Route::get('/donation', [DonationController::class, 'index'])->name('donation.index');
Route::get('/donation/create', [DonationController::class, 'create'])->name('donation.create'
Route::post('/donation', [DonationController::class, 'store'])->name('donation.store');
Route::get('/donation/{donation}', [DonationController::class, 'show'])->name('donation.show'
Route::get('/donation/{donation}/edit', [DonationController::class, 'edit'])->name('donation.
Route::put('/donation/{donation}', [DonationController::class, 'update'])->name('donation.upd
Route::delete('/donation/{donation}', [DonationController::class, 'destroy'])->name('donation
Dengan menggunakan route model binding kita bisa mengambil data dari model berdasarkan
parameter yang ada di URL, lalu menggunakan objek tersebut ke dalam controller untuk di
lakukan pemroresan lebih lanjut.
Bayangkan kamu punya route seperti ini:
Tanpa menggunakan route model binding mungkin contoller kalian seperti dibawah ini
Namun jika kita menggunakan model binding maka Laravel akan mencoba untuk melakujkan
pencocokan parameter yang ada di router dengan primary key yang ada dalam
database, jika sesuai maka variable yang di assign akan berisikan data yang berasal dari
model sehingga code dalam contoller kita lebih pendek, contohnya sebagai berikut
71
• Meningkatkan security
• Proses development menjadi lebih cepat
• Kode menjadi lebih mudah di baca dan di maintance
Ketika dihadapakan dengan project yang besar seringkali file route web.php menjadi sangat
panjang, hal ini kurang baik karena kita akan menjadi sasah untuk maintance file tersebut,
apalagi kalau dalam tim kita ada banyak developer yang secara bersamaan mengedit file yang
sama, maka akan terjadi mimpi buruk git conflict
Maka dari itu, memisahkan file router berdasarkan domain fitur, context atau role sangat
saya rekomendasikan sebagai best practice dalam pengembangan aplikasi laravel pada skala
aplikasi besar-menengah. Hal ini karena kita akan lebih mudah untuk melakukan maintance,
file router kita lebih terorganisir dan memudahkan kita untuk melakukan kolaborasi antar
anggota team.
Cara Memisahkan FIle router
Pada kasus kali ini saya akan memisahkan file router berdasarkan roles yang ada dalam aplikasi,
anggap saya di aplikasi kita terdapat role admin dan user, maka saya akan membuat route
admin.php dan user.php dengan tahapan sebagai berikut:
use Illuminate\Support\Facades\Route;
Route::group([
'namespace' => 'App\Http\Controllers\Admin',
'prefix' => 'admin',
'middleware' => ['role:admin']
], function () {
Route::get('','AdminController@dashboard');
Route::get('/users','UserController@index');
....
});
72
3. Mendaftarkan pada sistem Laravel
Jika menggunakan Laravel 11 Kebawah maka kita perlu mendaftarkan file yang baru
saja kita buat ke RouteServiceProvider
public function boot(): void
{
parent::boot();
$this->routes(function () {
Untuk pengguna Laravel 12+ maka perlu menambahkan pada bootstrap/app.php pada
function withRouting contohnya sebagai berikut
<?php
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
use Sentry\Laravel\Integration;
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
api: __DIR__.'/../routes/api.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
then: function(){
Route::prefix('admin')
->middleware('admin')
->group(base_path('routes/admin.php'));
}
)
})->create();
Dengan demikian file router kita sudah terorganisir dengan baik, dan akan memudahkan kita
73
untuk mengerjakan project yang cukup besar.
Laravel memperbolehkan kita untuk menuliskan clousure pada router secara langsung, con-
tohnya seperti berikut
<?php
use Illuminate\Support\Facades\Route;
Meskipun terlihat sederhana diawal jika kita menuliskan Closure pada router kedepannya hal
ini akan menjadi masalah yang serius pada pengembangan aplikasi. maka jika sudah terlan-
jur sangat disarankan untuk memindahkan logika dari clouse ke dalam controller.
Adanya controller membuat kode yang ditulis menjadi lebih mudah dibaca, dimaintance dan
memungkinkan kita untuk menggunakan semua fitur yang ada di dalam Laravel
74
Helper Function Solusi untuk Kode yang
Reusable dan Konsisten
Ketika kita sedang mengembangkan suatu proyek aplikasi, seringkali kita menuliskan fungsi
yang sama di berbagai tempat, misal saja ada kebutuhan untuk melakukan formating nilai
mata uang pada halaman invoice, maka kita akan menggunakan fungsi number_format .
Hal yang sering terjadi dalah kita tidak hanya melakukan formating rupiah pada satu halaman
biasanya ada kasus dimana kita melakukannya di halaman konfirmasi pembayara, tagihan,
daftar pembelian dan yang lainnya. Menuliskan "Rp " . number_format("10000", 2, ",",
"."); di berbagai tempat tersebut menjadi tidak efektif karena jika ada perubahan format
kita harus melakukannya di berbagai tempat, maka solusinya adalah dengan membuat Helper
Function.
Helper function adalah fungsi PHP yang dapat kita panggil dari mana saja dalam aplikasi
yang kita kembangkan tanpa perlu menginstansiasi kelas atau memanggil method tertentu.
Laravel punya banyak helper function bawaan yang sangat berguna untuk berbagai hal, mulai
dari manipulasi string, array, number dan sampai dengan debugging. Selain itu kita juga bisa
membantu Helper function yang bisa kita sesuaikan dengan kebutuhan, tanpa bergantung
pada helper yang sudah disediakan oleh Laravel.
Salah satu pertanyaan yang cukup sering muncul saat mengembangkan aplikasi Laravel adalah,
“Kapan sebaiknya kita menggunakan helper function?” Jawabannya berkaitan erat dengan
tujuan dari helper itu sendiri: menyederhanakan kode yang sering digunakan berulang kali di
berbagai tempat.
Helper function sangat cocok digunakan ketika kita ingin membuat kode yang lebih ringkas
dan mudah digunakan ulang — baik di dalam view, controller, maupun class lain. Biasanya,
fungsi-fungsi yang layak dijadikan helper bersifat sederhana dan stateless, artinya tidak
menyimpan kondisi atau bergantung pada proses lain. Contoh paling umum adalah fungsi
untuk memformat mata uang, mengonversi tanggal, atau memotong teks.
75
Selain itu, helper function idealnya tidak bergantung pada instance lain di aplikasi.
Artinya, fungsi tersebut tidak seharusnya terhubung langsung dengan model, database, atau
memerlukan dependency injection. Begitu sebuah fungsi mulai membutuhkan resource ekster-
nal atau menjadi terlalu kompleks, biasanya itu sudah bukan wilayahnya helper — dan lebih
tepat ditangani oleh service class atau komponen lain yang lebih terstruktur.
Menambahkan helper function berarti kita menambahkan satu lapisan baru ke dalam struktur
aplikasi. Meskipun helper sangat membantu untuk membuat kode lebih efisien dan reusable,
bukan berarti semua kebutuhan harus diselesaikan dengan helper function. Peng-
gunaan yang tidak tepat justru bisa membuat arsitektur aplikasi menjadi tidak rapi dan lebih
sulit dipelihara.
Karena itu, penting untuk mengenali kapan tidak menggunakan helper function. Hindari
membuat helper function ketika logika di dalamnya sudah terlalu kompleks, melibatkan banyak
kondisi, atau membutuhkan resource seperti dependency atau akses database. Helper bukan
tempat untuk menampung logika berat, lebih baik pindahkan ke service class yang memang
didesain untuk menangani hal tersebut.
Selain itu, jika ternyata kode akan lebih jelas dan mudah dibaca tanpa harus menggunakan
helper function, jangan paksakan penggunaannya. Kadang-kadang, terlalu banyak abstraksi
justru mengaburkan maksud dari kode itu sendiri. Prinsip utamanya tetap: gunakan helper
untuk menyederhanakan, bukan malah membingungkan.
Seperti yang kita semua tau, Laravel telah menyediakan banyak helper function untuk berbagai
keperluan, dari mulai manupulasi string, tipe data hingga debungging, semua helper function
tersebut bisa kita baca pada Halaman Dokumentasi Laravel. Beberapa Helper function yang
sering digunakan antara lain:
76
• array_pluck(): Mengambil nilai dari kolom tertentu dalam array multidimensi.
3. Collection Helpers
• collect(): Membuat koleksi Laravel dari array biasa, memungkinkan penggunaan
berbagai metode chaining.
• collect()->pluck(): Mengambil elemen dari koleksi berdasarkan kunci tertentu.
4. URL dan Path Helpers
• url(): Membuat URL lengkap untuk aplikasi.
• asset(): Membuat URL untuk file asset, seperti gambar atau CSS.
5. Debugging Helpers
• dd(): Dump and die, menampilkan variabel dan menghentikan eksekusi.
• dump(): Menampilkan informasi tentang variabel tanpa menghentikan eksekusi.
Jika semua helper function yang sudah ada, belum juga sesuai dengan kebutuhan kita maka
kita bisa membantu custom helper function yang bebas kita buat sesuai kebutuhan.
Walaupun sudah banyak helper function yang ada diLaravel, sering kali kita membutuhkan
fungsi khusus sesuai dengan kebutuhan aplikasi. Untuk itu kita bisa membuat custom helper
functions. Berikut ini adalah langkah-langkahnya:
Membuat file Helper Function
KIta bisa membuat folder khusus yang menyimpan semua file Helper yang ada dalam aplikasi
yang sedang kita kembangkan, biasanya saya membuatnya di folder app/Helpers misalkan kita
membuat StringHelper maka akan menjadi **app/Helpers/Currency**Helper.php Pada
helper file yang saya buat saya menuliskan fungsi untuk melakukan formating ke rupiah.
<?php
if (! function_exists('format_rupiah')) {
function format_rupiah($number) {
return 'Rp ' . number_format($number, 2, ',', '.');
}
}
Mendaftarkan di Composer
Setelah membuat file helper supaya fungsi yangs udah dibuat bisa dieksekusi di berbagai
tempat di Laravel kita maka kita perlu untuk mendaftarkan-nya pada composer.json , kita
akan menambahkan-nya pada bagian autoload > files seperti contoh dibawah ini
77
"autoload": {
"files": [
"app/Helpers/**Currency**Helper.php"
]
}
<?php
Helper function, baik yang bawaan atau custom, merupakan alat yang sangat berguna dalam
pengembangan aplikasi Laravel. Fungsi-fungsi ini memungkinkan Anda untuk membuat kode
78
yang lebih efisien dan dapat digunakan ulang, serta membantu menjaga kebersihan dan keter-
bacaan kode. Menggunakan helper dengan bijak dan menyesuaikannya dengan kebutuhan
aplikasi adalah kunci untuk menjaga aplikasi tetap sederhana dan mudah dipelihara.
79
Implementasi Form Request untuk Validasi
Modular
Pernah nggak, kamu bikin controller yang awalnya pendek tapi lama-lama jadi makin panjang
gara-gara validasi input user yang sangat panjang? Hampir semua dari kita yang menggunakan
Laravel untuk mengembangkan aplikasi sudah tidak asing lagi dengan validasi input user pada
controller, pada kasus sederhana saya menuliskannya dengan gaya langsung pada controller,
seperti berikut ini:
<?php
// ....
}
Tidak ada yang salah dari fungsi yang saya tulis sebelumnya, kita bisa melakukan validasi
request yang diberikan oleh user pada title dan body dengan berbagai aturan yang kita
terapkan.
Namun ketika kita dihadapkan pada suatu kondisi dimana diharuskan untuk melakukan vali-
dasi pada user input yang memiliki banyak variable dan atau dibutuhkan validasi yang memer-
lukan customisasi, sehingga menggunakan validasi bawaan dari laravel tidak cukup, maka
sebagai solusi-nya kita bisa menggunakan FormRequest
80
Laravel Form Request
Form Request merupakan fitur bawaan Laravel yang membuat kita memisahkan validasi
ke dalam kelas tersendiri. Dengan pendekatan ini, kita bisa menulis aturan validasi, pesan
kustom, bahkan transformasi data sebelum sampai ke controller dan semua di satu tempat
yang terpisah dan terstruktur. Kalau controller itu chef, maka FormRequest adalah asisten
dapur yang siap memfilter bahan sebelum dimasak.
Untuk membuat Form Request kita cukup menjalankan perintah php artisan make:request
namaRequest contohnya berikut ini:
Laravel akan membuat file baru di dalam folder app/Http/Request didalam file baru tersebut
akan terdapat dua method penting yaitu rules() dan authorize() yang masing-masing
memiliki fungsi sebagai berikut:
Untuk mempermudah pembahasan kali ini, berikut ini adalah contoh dari isi file Form Request
StoreDonationRequest.php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
/**
* Aturan validasi untuk request donasi.
81
*/
public function rules(): array
{
return [
'name' => 'required|string|max:100',
'email' => 'required|email',
'amount' => 'required|numeric|min:10000',
'message' => 'nullable|string|max:500',
'payment_method' => 'required|in:bank_transfer,qris,ewallet',
];
}
Dengan struktur seperti di atas, kita sudah berhasil memindahkan seluruh logika vali-
dasi ke tempat yang lebih terpisah dan modular. Controller sekarang tidak lagi perlu
menuliskan aturan satu per satu, karena Laravel akan otomatis menjalankan validasi dari
Form Request sebelum masuk ke controller. Ini berarti, jika ada input yang tidak valid, maka
user akan langsung mendapatkan respon error — tanpa kita harus menangani manual di
controller.
Untuk menggunakannya juga cukup serderhana, kita hanya perlu mengganti parameter
equest $request di controller menjadi StoreDonationRequest $request Laravel akan
otomatis meng-inject kelas tersebut dan melakukan validasi berdasarkan rules yang sudah
kita tulis sebelumnya.
Dengan pola ini, controller menjadi jauh lebih bersih dan fokus pada tugas utamanya, Kita
tidak perlu lagi memikirkan aturan validasi di sini, karena semuanya sudah ditangani oleh
Form Request secara terpisah.
Form Request bukan cuma tempat untuk menaruh aturan validasi kita juga bisa melakukan
kustomisasi sesuai dengan kebutuhan. Semakin kompleks aplikasi yang kita bangun, se-
makin besar manfaat dari fitur-fitur kustomisasi ini, baik untuk meningkatkan user experience
82
maupun untuk menjaga agar kode kita tetap bersih dan terstruktur. Di bagian ini, kita akan
membahas beberapa kustomisasi yang populer untuk menyesuaikan Form Request agar lebih
powerful dan relevan dengan konteks aplikasi kita
Secara default Laravel menyediakan pesan error yang cukup informatif, tapi terkadang ku-
rang sesuai dengan bahasa yang kita gunakan. Nah, dengan method messages(), kita bisa
mengganti pesan-pesan error ini dengan versi sesuai dengan kenginan kita. Caranya cukup
dengan mengembalikan array yang berisi aturan validasi sebagai key dan pesan yang ingin
ditampilkan sebagai value.
Dengan begini, pesan error yang muncul saat validasi gagal akan lebih baik, hal ini yang
akan membantu pengguna aplikasi supaya bisa memperbaiki data yang dikirimkannya pada
sistem.
Selain isi pesan error, kita juga bisa mengganti nama field yang ditampilkan di dalam pesan
error. Laravel secara default akan menampilkan nama field sesuai yang tertulis di form —
misalnya payment_method. Tapi bagi user awam, nama seperti itu bisa membingungkan.
maka dari itu kita akan menggunakan attributes() untuk melakukannya, contohnya sebagai
berikut:
83
'message' => 'pesan dukungan',
'payment_method' => 'metode pembayaran',
];
}
Setelah membuat method attributes(), jika ada error pada field payment_method, user
akan melihat pesan seperti “metode pembayaran wajib diisi”, bukan “payment_method is
required”.
Dan masih banyak lagi kustomisasi yang bisa kalian lakukan, untuk lebih lenmgkap-nya kalian
bisa membaca pada halaman validation di Laravel documentation
84