CRUD (Create, Read, Update, Delete) adalah fondasi dari banyak aplikasi web. Jika kamu sedang belajar Laravel dan ingin memahami bagaimana melakukan operasi CRUD dengan database MySQL, kamu berada di tempat yang tepat! Artikel ini akan memberikan contoh CRUD Laravel sederhana dengan database MySQL yang lengkap dan mudah diikuti. Kita akan membahasnya langkah demi langkah, mulai dari pengaturan awal hingga implementasi setiap operasi CRUD. Studi kasus yang kita gunakan akan memudahkan pemahamanmu. Mari kita mulai!
1. Persiapan Awal: Instalasi Laravel dan Konfigurasi Database MySQL
Sebelum memulai, pastikan kamu sudah memiliki beberapa hal berikut:
- PHP: Pastikan PHP sudah terinstall di komputermu. Laravel membutuhkan PHP versi 7.4 atau lebih tinggi.
- Composer: Composer adalah dependency manager untuk PHP. Unduh dan instal Composer dari https://getcomposer.org/.
- MySQL: Pastikan MySQL sudah terinstall dan berjalan. Kamu bisa menggunakan XAMPP, MAMP, atau sejenisnya.
- Node.js dan NPM (Opsional, tapi direkomendasikan): Untuk mengelola aset frontend.
Setelah semua persiapan terpenuhi, mari kita mulai dengan menginstal Laravel. Buka terminal atau command prompt, lalu jalankan perintah berikut:
composer create-project --prefer-dist laravel/laravel crud-laravel-mysql
cd crud-laravel-mysql
Perintah ini akan membuat project Laravel baru dengan nama crud-laravel-mysql
. Setelah project berhasil dibuat, masuk ke direktori project tersebut.
Selanjutnya, kita perlu mengkonfigurasi koneksi ke database MySQL. Buka file .env
di direktori project. Cari bagian yang berisi pengaturan database, lalu sesuaikan dengan informasi database MySQL kamu:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=nama_database_anda
DB_USERNAME=username_database_anda
DB_PASSWORD=password_database_anda
Ganti nama_database_anda
, username_database_anda
, dan password_database_anda
dengan informasi yang sesuai. Pastikan database yang kamu tentukan sudah dibuat di MySQL.
2. Membuat Migrasi dan Model: Struktur Database untuk CRUD
Sekarang kita akan membuat migrasi untuk membuat tabel di database dan model yang akan berinteraksi dengan tabel tersebut. Kita akan membuat contoh CRUD untuk data “Produk”.
Jalankan perintah berikut di terminal:
php artisan make:migration create_produks_table --create=produks
php artisan make:model Produk
Perintah pertama akan membuat file migrasi baru di direktori database/migrations
. Perintah kedua akan membuat model baru di direktori app/Models
.
Buka file migrasi yang baru dibuat (biasanya namanya mirip YYYY_MM_DD_HHMMSS_create_produks_table.php
). Edit file tersebut sehingga terlihat seperti ini:
<?php
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('produks', function (Blueprint $table) {
$table->id();
$table->string('nama');
$table->text('deskripsi')->nullable();
$table->decimal('harga', 10, 2);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('produks');
}
};
Kode ini akan membuat tabel bernama produks
dengan kolom id
, nama
, deskripsi
, harga
, created_at
, dan updated_at
.
Selanjutnya, buka file model app/Models/Produk.php
dan tambahkan kode berikut:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;
class Produk extends Model
{
use HasFactory;
protected $fillable = [
'nama',
'deskripsi',
'harga',
];
}
$fillable
menentukan kolom mana saja yang boleh diisi (mass assignment). Ini penting untuk keamanan.
Terakhir, jalankan migrasi untuk membuat tabel di database:
php artisan migrate
3. Membuat Controller: Menangani Logika CRUD
Kita akan membuat controller untuk menangani semua logika CRUD. Jalankan perintah berikut di terminal:
php artisan make:controller ProdukController
Perintah ini akan membuat file controller baru di direktori app/Http/Controllers
. Buka file app/Http/Controllers/ProdukController.php
dan tambahkan kode berikut:
<?php
namespace AppHttpControllers;
use AppModelsProduk;
use IlluminateHttpRequest;
class ProdukController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
$produks = Produk::all();
return view('produks.index', compact('produks'));
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
return view('produks.create');
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
$request->validate([
'nama' => 'required',
'harga' => 'required|numeric',
]);
Produk::create($request->all());
return redirect()->route('produks.index')
->with('success', 'Produk berhasil ditambahkan.');
}
/**
* Display the specified resource.
*/
public function show(Produk $produk)
{
return view('produks.show', compact('produk'));
}
/**
* Show the form for editing the specified resource.
*/
public function edit(Produk $produk)
{
return view('produks.edit', compact('produk'));
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, Produk $produk)
{
$request->validate([
'nama' => 'required',
'harga' => 'required|numeric',
]);
$produk->update($request->all());
return redirect()->route('produks.index')
->with('success', 'Produk berhasil diperbarui.');
}
/**
* Remove the specified resource from storage.
*/
public function destroy(Produk $produk)
{
$produk->delete();
return redirect()->route('produks.index')
->with('success', 'Produk berhasil dihapus.');
}
}
Controller ini memiliki tujuh method: index
, create
, store
, show
, edit
, update
, dan destroy
. Masing-masing method bertanggung jawab untuk operasi CRUD yang berbeda.
4. Membuat Views: Tampilan Antarmuka CRUD dengan Blade
Kita akan membuat views menggunakan Blade templating engine untuk menampilkan data dan form. Buat folder produks
di dalam folder resources/views
. Di dalam folder produks
, buat file-file berikut:
index.blade.php
: Menampilkan daftar produk.create.blade.php
: Form untuk menambahkan produk baru.show.blade.php
: Menampilkan detail produk.edit.blade.php
: Form untuk mengedit produk.
Berikut adalah contoh kode untuk setiap view:
resources/views/produks/index.blade.php
:
<!DOCTYPE html>
<html>
<head>
<title>Daftar Produk</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<h2>Daftar Produk</h2>
<a href="{{ route('produks.create') }}" class="btn btn-success mb-3">Tambah Produk</a>
@if ($message = Session::get('success'))
<div class="alert alert-success">
<p>{{ $message }}</p>
</div>
@endif
<table class="table table-bordered">
<tr>
<th>ID</th>
<th>Nama</th>
<th>Deskripsi</th>
<th>Harga</th>
<th>Aksi</th>
</tr>
@foreach ($produks as $produk)
<tr>
<td>{{ $produk->id }}</td>
<td>{{ $produk->nama }}</td>
<td>{{ $produk->deskripsi }}</td>
<td>{{ $produk->harga }}</td>
<td>
<form action="{{ route('produks.destroy',$produk->id) }}" method="POST">
<a class="btn btn-info" href="{{ route('produks.show',$produk->id) }}">Show</a>
<a class="btn btn-primary" href="{{ route('produks.edit',$produk->id) }}">Edit</a>
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
@endforeach
</table>
</div>
</body>
</html>
resources/views/produks/create.blade.php
:
<!DOCTYPE html>
<html>
<head>
<title>Tambah Produk</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<h2>Tambah Produk</h2>
<a href="{{ route('produks.index') }}" class="btn btn-secondary mb-3">Kembali</a>
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form action="{{ route('produks.store') }}" method="POST">
@csrf
<div class="form-group">
<label for="nama">Nama:</label>
<input type="text" class="form-control" id="nama" name="nama">
</div>
<div class="form-group">
<label for="deskripsi">Deskripsi:</label>
<textarea class="form-control" id="deskripsi" name="deskripsi"></textarea>
</div>
<div class="form-group">
<label for="harga">Harga:</label>
<input type="number" step="0.01" class="form-control" id="harga" name="harga">
</div>
<button type="submit" class="btn btn-primary">Simpan</button>
</form>
</div>
</body>
</html>
resources/views/produks/show.blade.php
:
<!DOCTYPE html>
<html>
<head>
<title>Detail Produk</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<h2>Detail Produk</h2>
<a href="{{ route('produks.index') }}" class="btn btn-secondary mb-3">Kembali</a>
<div class="card">
<div class="card-body">
<h5 class="card-title">{{ $produk->nama }}</h5>
<p class="card-text">{{ $produk->deskripsi }}</p>
<p class="card-text">Harga: Rp. {{ number_format($produk->harga, 2) }}</p>
</div>
</div>
</div>
</body>
</html>
resources/views/produks/edit.blade.php
:
<!DOCTYPE html>
<html>
<head>
<title>Edit Produk</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<h2>Edit Produk</h2>
<a href="{{ route('produks.index') }}" class="btn btn-secondary mb-3">Kembali</a>
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form action="{{ route('produks.update', $produk->id) }}" method="POST">
@csrf
@method('PUT')
<div class="form-group">
<label for="nama">Nama:</label>
<input type="text" class="form-control" id="nama" name="nama" value="{{ $produk->nama }}">
</div>
<div class="form-group">
<label for="deskripsi">Deskripsi:</label>
<textarea class="form-control" id="deskripsi" name="deskripsi">{{ $produk->deskripsi }}</textarea>
</div>
<div class="form-group">
<label for="harga">Harga:</label>
<input type="number" step="0.01" class="form-control" id="harga" name="harga" value="{{ $produk->harga }}">
</div>
<button type="submit" class="btn btn-primary">Update</button>
</form>
</div>
</body>
</html>
Pastikan kamu sudah menginstall Bootstrap untuk tampilan yang lebih baik. Kamu bisa menambahkan link ke CDN Bootstrap seperti pada contoh kode di atas.
5. Konfigurasi Route: Menghubungkan URL dengan Controller
Kita perlu mendefinisikan route yang akan menghubungkan URL dengan method di controller. Buka file routes/web.php
dan tambahkan kode berikut:
<?php
use IlluminateSupportFacadesRoute;
use AppHttpControllersProdukController;
Route::resource('produks', ProdukController::class);
Route::resource
secara otomatis akan membuat route untuk semua operasi CRUD yang dibutuhkan. Ini adalah cara yang paling efisien untuk membuat route untuk resource CRUD.
6. Uji Coba Aplikasi CRUD Sederhana dengan MySQL di Laravel
Sekarang, saatnya untuk menguji coba aplikasi CRUD yang telah kita buat. Jalankan server pengembangan Laravel dengan perintah:
php artisan serve
Buka browser dan kunjungi http://localhost:8000/produks
. Kamu akan melihat tampilan daftar produk (yang masih kosong). Klik tombol “Tambah Produk” untuk menambahkan produk baru. Setelah menambahkan beberapa produk, kamu akan melihat daftar produk yang telah kamu tambahkan. Kamu juga bisa mengedit dan menghapus produk.
Tips Pemecahan Masalah:
- Error Database: Pastikan koneksi database di file
.env
sudah benar. Periksa juga apakah database sudah dibuat. - Error Route: Pastikan route sudah didefinisikan dengan benar di file
routes/web.php
. - Error View: Pastikan nama file view sudah benar dan terletak di direktori yang benar (
resources/views
). - Error Model: Pastikan properti
$fillable
di model sudah diisi dengan benar.
7. Validasi Input: Menjamin Keamanan dan Integritas Data
Validasi input sangat penting untuk keamanan dan integritas data. Kita sudah menambahkan validasi sederhana di method store
dan update
di ProdukController
. Namun, kita bisa menambahkan validasi yang lebih kompleks.
Laravel menyediakan berbagai macam rule validasi yang bisa kamu gunakan. Kamu bisa melihat daftar lengkapnya di dokumentasi Laravel: https://laravel.com/docs/validation.
Contoh validasi yang lebih kompleks:
public function store(Request $request)
{
$request->validate([
'nama' => 'required|string|max:255',
'deskripsi' => 'nullable|string',
'harga' => 'required|numeric|min:0',
]);
Produk::create($request->all());
return redirect()->route('produks.index')
->with('success', 'Produk berhasil ditambahkan.');
}
Kita menambahkan validasi bahwa nama
harus berupa string dengan panjang maksimal 255 karakter, deskripsi
boleh kosong dan harus berupa string, dan harga
harus berupa angka dengan nilai minimal 0.
8. Otentikasi: Mengamankan Akses ke Fungsi CRUD
Secara default, semua route di aplikasi kita bisa diakses oleh siapa saja. Untuk mengamankan akses ke fungsi CRUD, kita perlu menambahkan otentikasi.
Laravel menyediakan package otentikasi yang sangat mudah digunakan: Laravel Breeze atau Laravel Jetstream. Mari kita gunakan Laravel Breeze. Jalankan perintah berikut di terminal:
composer require laravel/breeze --dev
php artisan breeze:install
npm install
npm run dev
php artisan migrate
Setelah instalasi selesai, kamu bisa mendaftarkan user baru dan login. Untuk melindungi route produks
, tambahkan middleware auth
ke route tersebut:
Route::resource('produks', ProdukController::class)->middleware('auth');
Sekarang, hanya user yang sudah login yang bisa mengakses route produks
.
9. Relasi Database: Menghubungkan Tabel Produk dengan Tabel Lain
Contoh CRUD kita masih sangat sederhana. Dalam aplikasi yang lebih kompleks, biasanya kita perlu menghubungkan tabel produk dengan tabel lain, misalnya tabel kategori.
Misalkan kita ingin menghubungkan tabel produks
dengan tabel kategoris
. Pertama, buat migrasi dan model untuk tabel kategoris
:
php artisan make:migration create_kategoris_table --create=kategoris
php artisan make:model Kategori
Edit file migrasi database/migrations/YYYY_MM_DD_HHMMSS_create_kategoris_table.php
:
<?php
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('kategoris', function (Blueprint $table) {
$table->id();
$table->string('nama');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('kategoris');
}
};
Edit file model app/Models/Kategori.php
:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;
class Kategori extends Model
{
use HasFactory;
protected $fillable = [
'nama',
];
public function produks()
{
return $this->hasMany(Produk::class);
}
}
Selanjutnya, tambahkan kolom kategori_id
ke tabel produks
. Buat migrasi baru:
php artisan make:migration add_kategori_id_to_produks_table
Edit file migrasi database/migrations/YYYY_MM_DD_HHMMSS_add_kategori_id_to_produks_table.php
:
<?php
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('produks', function (Blueprint $table) {
$table->unsignedBigInteger('kategori_id')->nullable();
$table->foreign('kategori_id')->references('id')->on('kategoris')->onDelete('set null');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('produks', function (Blueprint $table) {
$table->dropForeign(['kategori_id']);
$table->dropColumn('kategori_id');
});
}
};
Edit file model app/Models/Produk.php
:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;
class Produk extends Model
{
use HasFactory;
protected $fillable = [
'nama',
'deskripsi',
'harga',
'kategori_id',
];
public function kategori()
{
return $this->belongsTo(Kategori::class);
}
}
Jalankan migrasi:
php artisan migrate
Sekarang, tabel produks
memiliki kolom kategori_id
yang terhubung dengan tabel kategoris
. Kamu bisa menggunakan relasi ini untuk menampilkan kategori produk di view.
10. Optimasi Query: Meningkatkan Performa Aplikasi CRUD
Optimasi query sangat penting untuk performa aplikasi CRUD. Salah satu teknik optimasi yang paling umum adalah menggunakan eager loading.
Contohnya, jika kita ingin menampilkan daftar produk beserta nama kategorinya, kita bisa menggunakan eager loading untuk memuat relasi kategori secara efisien.
$produks = Produk::with('kategori')->get();
Dengan eager loading, Laravel hanya akan menjalankan dua query: satu untuk mengambil semua produk dan satu lagi untuk mengambil semua kategori yang terkait dengan produk tersebut. Tanpa eager loading, Laravel akan menjalankan satu query untuk setiap produk untuk mengambil kategori yang terkait. Ini bisa sangat lambat jika kita memiliki banyak produk.
Teknik optimasi lainnya termasuk:
- Indexing: Pastikan kolom yang sering digunakan dalam query (misalnya kolom
nama
,harga
,kategori_id
) memiliki index. - Caching: Gunakan caching untuk menyimpan hasil query yang sering digunakan.
- Pagination: Gunakan pagination untuk membatasi jumlah data yang ditampilkan di halaman.
11. Penggunaan Form Request: Validasi Lebih Terstruktur dan Bersih
Form Request adalah cara yang lebih terstruktur dan bersih untuk melakukan validasi di Laravel. Daripada melakukan validasi langsung di controller, kita bisa membuat class Form Request khusus untuk setiap request.
Jalankan perintah berikut untuk membuat Form Request:
php artisan make:request ProdukRequest
Edit file app/Http/Requests/ProdukRequest.php
:
<?php
namespace AppHttpRequests;
use IlluminateFoundationHttpFormRequest;
class ProdukRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true; // Ubah menjadi false jika ada otorisasi khusus
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, IlluminateContractsValidationValidationRule|array|string>
*/
public function rules(): array
{
return [
'nama' => 'required|string|max:255',
'deskripsi' => 'nullable|string',
'harga' => 'required|numeric|min:0',
'kategori_id' => 'nullable|exists:kategoris,id', // Validasi jika kategori_id ada di tabel kategoris
];
}
}
Sekarang, ubah controller untuk menggunakan Form Request:
<?php
namespace AppHttpControllers;
use AppModelsProduk;
use AppHttpRequestsProdukRequest; // Import ProdukRequest
use IlluminateHttpRequest;
class ProdukController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
$produks = Produk::with('kategori')->get(); // Eager loading untuk performa
return view('produks.index', compact('produks'));
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
$kategoris = AppModelsKategori::all(); // Ambil semua kategori untuk dropdown
return view('produks.create', compact('kategoris'));
}
/**
* Store a newly created resource in storage.
*/
public function store(ProdukRequest $request) // Gunakan ProdukRequest
{
Produk::create($request->validated()); // Gunakan data yang sudah divalidasi
return redirect()->route('produks.index')
->with('success', 'Produk berhasil ditambahkan.');
}
/**
* Display the specified resource.
*/
public function show(Produk $produk)
{
return view('produks.show', compact('produk'));
}
/**
* Show the form for editing the specified resource.
*/
public function edit(Produk $produk)
{
$kategoris = AppModelsKategori::all(); // Ambil semua kategori untuk dropdown
return view('produks.edit', compact('produk', 'kategoris'));
}
/**
* Update the specified resource in storage.
*/
public function update(ProdukRequest $request, Produk $produk) // Gunakan ProdukRequest
{
$produk->update($request->validated()); // Gunakan data yang sudah divalidasi
return redirect()->route('produks.index')
->with('success', 'Produk berhasil diperbarui.');
}
/**
* Remove the specified resource from storage.
*/
public function destroy(Produk $produk)
{
$produk->delete();
return redirect()->route('produks.index')
->with('success', 'Produk berhasil dihapus.');
}
}
Di method store
dan update
, kita menggunakan ProdukRequest
untuk validasi. Dengan menggunakan ProdukRequest
, controller kita menjadi lebih bersih dan mudah dibaca.
12. Studi Kasus: Pengembangan Sistem Manajemen Produk Lengkap
Setelah memahami dasar-dasar CRUD dengan Laravel dan MySQL, mari kita lihat studi kasus pengembangan sistem manajemen produk yang lebih lengkap.
Fitur Tambahan:
- Upload Gambar: Tambahkan fitur untuk mengupload gambar produk. Gunakan library intervention/image untuk memanipulasi gambar.
- Pencarian: Tambahkan fitur pencarian produk berdasarkan nama, deskripsi, atau harga.
- Filter: Tambahkan fitur filter produk berdasarkan kategori, harga, atau status.
- Pagination: Terapkan pagination untuk menampilkan data produk secara bertahap.
- Laporan: Buat laporan penjualan produk.
- Import/Export: Tambahkan fitur untuk import dan export data produk dalam format CSV atau Excel.
Arsitektur Aplikasi:
- Model: Produk, Kategori, Gambar
- Controller: ProdukController, KategoriController
- View:
produks/index.blade.php
,produks/create.blade.php
,produks/show.blade.php
,produks/edit.blade.php
,kategoris/index.blade.php
,kategoris/create.blade.php
,kategoris/edit.blade.php
- Route: Resource route untuk produk dan kategori
- Middleware: Auth middleware untuk keamanan
Dengan studi kasus ini, kamu bisa mengaplikasikan pengetahuan yang telah kamu pelajari untuk mengembangkan aplikasi yang lebih kompleks dan bermanfaat.
Kesimpulan:
Artikel ini telah memberikan contoh CRUD Laravel sederhana dengan database MySQL yang lengkap dan mudah diikuti. Kita telah membahas langkah-langkah mulai dari instalasi Laravel, konfigurasi database, membuat migrasi dan model, membuat controller, membuat views, konfigurasi route, validasi input, otentikasi, relasi database, optimasi query, penggunaan Form Request, dan studi kasus pengembangan sistem manajemen produk lengkap. Semoga artikel ini bermanfaat dan membantumu dalam belajar Laravel! Selamat mencoba!