Laravel 9 adalah framework PHP yang powerful dan populer untuk membangun aplikasi web modern. Salah satu operasi dasar yang sering dibutuhkan dalam pengembangan web adalah CRUD (Create, Read, Update, Delete). Artikel ini akan memberikan panduan lengkap dan praktis tentang cara membuat CRUD dengan Laravel 9, khususnya ditujukan untuk para pemula. Mari kita mulai!
1. Apa Itu CRUD dan Mengapa Penting?
Sebelum kita masuk ke kode, mari kita pahami dulu apa itu CRUD dan mengapa itu penting. CRUD adalah singkatan dari:
- Create: Membuat data baru.
- Read: Membaca atau menampilkan data yang sudah ada.
- Update: Memperbarui data yang sudah ada.
- Delete: Menghapus data.
CRUD adalah operasi dasar yang hampir selalu ada dalam aplikasi web yang berinteraksi dengan database. Bayangkan sebuah aplikasi blog, aplikasi manajemen proyek, atau bahkan toko online. Semuanya membutuhkan CRUD untuk mengelola data artikel, tugas, atau produk. Memahami dan mampu mengimplementasikan CRUD dengan baik adalah fondasi penting dalam pengembangan web.
2. Persiapan Awal: Instalasi Laravel 9 dan Konfigurasi Database
Sebelum mulai coding, pastikan kamu sudah memiliki Laravel 9 terinstall di komputermu. Jika belum, ikuti langkah-langkah berikut:
-
Pastikan PHP dan Composer Terinstall: Laravel membutuhkan PHP (minimal versi 8.0) dan Composer (dependency manager untuk PHP). Pastikan keduanya sudah terinstall dengan benar. Kamu bisa mengeceknya dengan perintah
php -v
dancomposer -v
di terminal. -
Buat Proyek Laravel Baru: Buka terminal dan navigasikan ke direktori tempat kamu ingin membuat proyekmu. Kemudian, jalankan perintah berikut:
composer create-project laravel/laravel nama-proyek
Ganti
nama-proyek
dengan nama proyek yang kamu inginkan (misalnya,crud-sederhana
). -
Konfigurasi Database: Laravel menggunakan file
.env
untuk menyimpan konfigurasi lingkungan, termasuk konfigurasi database. Buka file.env
dan temukan bagian yang berkaitan dengan database. Sesuaikan dengan pengaturan database yang kamu gunakan (misalnya, MySQL, PostgreSQL, atau SQLite). Contoh konfigurasi untuk MySQL:DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=nama_database_kamu DB_USERNAME=username_database_kamu DB_PASSWORD=password_database_kamu
Ganti
nama_database_kamu
,username_database_kamu
, danpassword_database_kamu
dengan detail database yang sudah kamu buat. -
Jalankan Migrasi Default: Laravel menyediakan migrasi default untuk tabel
users
danpassword_resets
. Jalankan migrasi ini dengan perintah:
php artisan migrate
Setelah langkah-langkah ini selesai, Laravel 9 siap untuk digunakan.
3. Membuat Model dan Migrasi untuk Data yang Akan Dikelola
Langkah selanjutnya adalah membuat model dan migrasi untuk data yang akan kita kelola. Dalam contoh ini, kita akan membuat CRUD untuk data Artikel
.
-
Buat Model: Gunakan perintah
artisan
untuk membuat model:php artisan make:model Artikel -m
Perintah ini akan membuat dua file:
app/Models/Artikel.php
(model) dandatabase/migrations/xxxx_xx_xx_xxxxxx_create_artikels_table.php
(migrasi). Opsi-m
secara otomatis membuat file migrasi bersamaan dengan model. -
Definisikan Schema Tabel di Migrasi: Buka file migrasi yang baru dibuat (yang ada di folder
database/migrations
). Editup()
method untuk mendefinisikan schema tabelartikels
. Misalnya, kita akan menyimpanjudul
,isi
, dantanggal_terbit
:<?php use IlluminateDatabaseMigrationsMigration; use IlluminateDatabaseSchemaBlueprint; use IlluminateSupportFacadesSchema; return new class extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('artikels', function (Blueprint $table) { $table->id(); $table->string('judul'); $table->text('isi'); $table->date('tanggal_terbit')->nullable(); // Bisa null jika tidak ada tanggal terbit $table->timestamps(); // Otomatis menambahkan `created_at` dan `updated_at` }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('artikels'); } };
-
Jalankan Migrasi: Setelah mendefinisikan schema, jalankan migrasi untuk membuat tabel di database:
php artisan migrate
-
Mass Assignment Protection: Di model
Artikel.php
, tambahkan properti$fillable
untuk mengizinkan mass assignment. Ini penting untuk keamanan.
<?php
namespace AppModels;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;
class Artikel extends Model
{
use HasFactory;
protected $fillable = ['judul', 'isi', 'tanggal_terbit'];
}
4. Membuat Controller untuk Mengelola Logika CRUD
Controller adalah tempat kita menulis logika untuk menangani permintaan HTTP (request) dan berinteraksi dengan model.
-
Buat Controller: Gunakan perintah
artisan
untuk membuat controller:php artisan make:controller ArtikelController
Ini akan membuat file
app/Http/Controllers/ArtikelController.php
. -
Definisikan Metode CRUD di Controller: Buka
ArtikelController.php
dan definisikan metode untuk masing-masing operasi CRUD:index
(menampilkan semua artikel),create
(menampilkan form untuk membuat artikel baru),store
(menyimpan artikel baru),show
(menampilkan detail artikel),edit
(menampilkan form untuk mengedit artikel),update
(memperbarui artikel), dandestroy
(menghapus artikel).Berikut contoh kerangka
ArtikelController.php
:<?php namespace AppHttpControllers; use AppModelsArtikel; use IlluminateHttpRequest; class ArtikelController extends Controller { /** * Display a listing of the resource. * * @return IlluminateHttpResponse */ public function index() { // Logika untuk menampilkan semua artikel } /** * Show the form for creating a new resource. * * @return IlluminateHttpResponse */ public function create() { // Logika untuk menampilkan form create } /** * Store a newly created resource in storage. * * @param IlluminateHttpRequest $request * @return IlluminateHttpResponse */ public function store(Request $request) { // Logika untuk menyimpan artikel baru } /** * Display the specified resource. * * @param AppModelsArtikel $artikel * @return IlluminateHttpResponse */ public function show(Artikel $artikel) { // Logika untuk menampilkan detail artikel } /** * Show the form for editing the specified resource. * * @param AppModelsArtikel $artikel * @return IlluminateHttpResponse */ public function edit(Artikel $artikel) { // Logika untuk menampilkan form edit } /** * Update the specified resource in storage. * * @param IlluminateHttpRequest $request * @param AppModelsArtikel $artikel * @return IlluminateHttpResponse */ public function update(Request $request, Artikel $artikel) { // Logika untuk memperbarui artikel } /** * Remove the specified resource from storage. * * @param AppModelsArtikel $artikel * @return IlluminateHttpResponse */ public function destroy(Artikel $artikel) { // Logika untuk menghapus artikel } }
5. Menentukan Routes untuk Mengakses Controller
Routes menentukan bagaimana URL di aplikasi kamu akan di-mapping ke controller dan method yang sesuai.
-
Buka File
routes/web.php
: File ini adalah tempat kita mendefinisikan routes web. -
Definisikan Resource Route: Gunakan method
resource
untuk secara otomatis membuat routes untuk semua operasi CRUD:<?php use IlluminateSupportFacadesRoute; use AppHttpControllersArtikelController; Route::resource('artikel', ArtikelController::class);
Ini akan membuat routes berikut:
GET /artikel
->ArtikelController@index
GET /artikel/create
->ArtikelController@create
POST /artikel
->ArtikelController@store
GET /artikel/{artikel}
->ArtikelController@show
GET /artikel/{artikel}/edit
->ArtikelController@edit
PUT/PATCH /artikel/{artikel}
->ArtikelController@update
DELETE /artikel/{artikel}
->ArtikelController@destroy
6. Mengimplementasikan Logika CRUD di Controller (Lengkap)
Sekarang, mari kita isi logika CRUD di ArtikelController.php
.
<?php
namespace AppHttpControllers;
use AppModelsArtikel;
use IlluminateHttpRequest;
use IlluminateSupportFacadesSession;
class ArtikelController extends Controller
{
/**
* Display a listing of the resource.
*
* @return IlluminateHttpResponse
*/
public function index()
{
$artikels = Artikel::latest()->paginate(10); // Ambil semua artikel, urutkan berdasarkan terbaru, paginasi 10 per halaman
return view('artikel.index', compact('artikels'))
->with('i', (request()->input('page', 1) - 1) * 10);
}
/**
* Show the form for creating a new resource.
*
* @return IlluminateHttpResponse
*/
public function create()
{
return view('artikel.create');
}
/**
* Store a newly created resource in storage.
*
* @param IlluminateHttpRequest $request
* @return IlluminateHttpResponse
*/
public function store(Request $request)
{
$request->validate([
'judul' => 'required',
'isi' => 'required',
'tanggal_terbit' => 'nullable|date', // Validasi tanggal (boleh null)
]);
Artikel::create($request->all());
Session::flash('success', 'Artikel berhasil ditambahkan.');
return redirect()->route('artikel.index')
->with('success', 'Artikel berhasil ditambahkan.'); // Flash message
}
/**
* Display the specified resource.
*
* @param AppModelsArtikel $artikel
* @return IlluminateHttpResponse
*/
public function show(Artikel $artikel)
{
return view('artikel.show', compact('artikel'));
}
/**
* Show the form for editing the specified resource.
*
* @param AppModelsArtikel $artikel
* @return IlluminateHttpResponse
*/
public function edit(Artikel $artikel)
{
return view('artikel.edit', compact('artikel'));
}
/**
* Update the specified resource in storage.
*
* @param IlluminateHttpRequest $request
* @param AppModelsArtikel $artikel
* @return IlluminateHttpResponse
*/
public function update(Request $request, Artikel $artikel)
{
$request->validate([
'judul' => 'required',
'isi' => 'required',
'tanggal_terbit' => 'nullable|date',
]);
$artikel->update($request->all());
Session::flash('success', 'Artikel berhasil diperbarui.');
return redirect()->route('artikel.index')
->with('success', 'Artikel berhasil diperbarui.'); // Flash message
}
/**
* Remove the specified resource from storage.
*
* @param AppModelsArtikel $artikel
* @return IlluminateHttpResponse
*/
public function destroy(Artikel $artikel)
{
$artikel->delete();
Session::flash('success', 'Artikel berhasil dihapus.');
return redirect()->route('artikel.index')
->with('success', 'Artikel berhasil dihapus.'); // Flash message
}
}
Penjelasan:
index()
: Mengambil semua artikel dari database menggunakan modelArtikel
. Menggunakanlatest()
untuk mengurutkan berdasarkan waktu pembuatan terbaru, danpaginate(10)
untuk membagi hasilnya menjadi halaman-halaman dengan 10 artikel per halaman. Kemudian, me-return viewartikel.index
dengan data artikel.create()
: Me-return viewartikel.create
, yang berisi form untuk membuat artikel baru.store(Request $request)
: Menerima data dari form (melalui$request
), melakukan validasi menggunakan$request->validate()
, membuat artikel baru menggunakanArtikel::create($request->all())
, dan kemudian redirect ke halamanartikel.index
. MenggunakanSession::flash()
untuk menampilkan pesan sukses.show(Artikel $artikel)
: Menerima instanceArtikel
sebagai parameter (otomatis di-resolve oleh Laravel berdasarkan route parameter). Me-return viewartikel.show
dengan data artikel.edit(Artikel $artikel)
: Menerima instanceArtikel
sebagai parameter. Me-return viewartikel.edit
dengan data artikel, untuk menampilkan form edit.update(Request $request, Artikel $artikel)
: Menerima data dari form edit (melalui$request
), melakukan validasi, memperbarui artikel menggunakan$artikel->update($request->all())
, dan kemudian redirect ke halamanartikel.index
. MenggunakanSession::flash()
untuk menampilkan pesan sukses.destroy(Artikel $artikel)
: Menerima instanceArtikel
sebagai parameter. Menghapus artikel menggunakan$artikel->delete()
dan kemudian redirect ke halamanartikel.index
. MenggunakanSession::flash()
untuk menampilkan pesan sukses.
7. Membuat Views untuk Menampilkan Data dan Form
Kita membutuhkan views untuk menampilkan data artikel, form untuk membuat dan mengedit artikel, dan layout dasar.
-
Buat Direktori
resources/views/artikel
: Di dalam direktoriresources/views
, buat direktori bernamaartikel
untuk menyimpan views yang berkaitan dengan artikel. -
Buat
index.blade.php
: File ini akan menampilkan daftar artikel.<!-- resources/views/artikel/index.blade.php --> @extends('layouts.app') @section('content') <div class="container"> <h2>Daftar Artikel</h2> <a href="{{ route('artikel.create') }}" class="btn btn-primary mb-3">Tambah Artikel Baru</a> @if(Session::has('success')) <div class="alert alert-success"> {{ Session::get('success') }} </div> @endif <table class="table"> <thead> <tr> <th>No</th> <th>Judul</th> <th>Isi</th> <th>Tanggal Terbit</th> <th>Aksi</th> </tr> </thead> <tbody> @foreach ($artikels as $artikel) <tr> <td>{{ ++$i }}</td> <td>{{ $artikel->judul }}</td> <td>{{ Str::limit($artikel->isi, 50) }}</td> <!-- Batasi tampilan isi --> <td>{{ $artikel->tanggal_terbit ? $artikel->tanggal_terbit->format('d-m-Y') : '-' }}</td> <td> <a href="{{ route('artikel.show', $artikel->id) }}" class="btn btn-sm btn-info">Lihat</a> <a href="{{ route('artikel.edit', $artikel->id) }}" class="btn btn-sm btn-warning">Edit</a> <form action="{{ route('artikel.destroy', $artikel->id) }}" method="POST" style="display: inline;"> @csrf @method('DELETE') <button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('Apakah Anda yakin ingin menghapus artikel ini?')">Hapus</button> </form> </td> </tr> @endforeach </tbody> </table> {!! $artikels->links() !!} <!-- Tampilkan link paginasi --> </div> @endsection
-
Buat
create.blade.php
: File ini akan menampilkan form untuk membuat artikel baru.<!-- resources/views/artikel/create.blade.php --> @extends('layouts.app') @section('content') <div class="container"> <h2>Tambah Artikel Baru</h2> @if ($errors->any()) <div class="alert alert-danger"> <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> @endif <form action="{{ route('artikel.store') }}" method="POST"> @csrf <div class="form-group"> <label for="judul">Judul:</label> <input type="text" class="form-control" id="judul" name="judul" value="{{ old('judul') }}" required> </div> <div class="form-group"> <label for="isi">Isi:</label> <textarea class="form-control" id="isi" name="isi" rows="5" required>{{ old('isi') }}</textarea> </div> <div class="form-group"> <label for="tanggal_terbit">Tanggal Terbit:</label> <input type="date" class="form-control" id="tanggal_terbit" name="tanggal_terbit" value="{{ old('tanggal_terbit') }}"> </div> <button type="submit" class="btn btn-primary">Simpan</button> <a href="{{ route('artikel.index') }}" class="btn btn-secondary">Batal</a> </form> </div> @endsection
-
Buat
show.blade.php
: File ini akan menampilkan detail artikel.<!-- resources/views/artikel/show.blade.php --> @extends('layouts.app') @section('content') <div class="container"> <h2>Detail Artikel</h2> <p><strong>Judul:</strong> {{ $artikel->judul }}</p> <p><strong>Isi:</strong> {{ $artikel->isi }}</p> <p><strong>Tanggal Terbit:</strong> {{ $artikel->tanggal_terbit ? $artikel->tanggal_terbit->format('d-m-Y') : '-' }}</p> <a href="{{ route('artikel.index') }}" class="btn btn-secondary">Kembali</a> </div> @endsection
-
Buat
edit.blade.php
: File ini akan menampilkan form untuk mengedit artikel.<!-- resources/views/artikel/edit.blade.php --> @extends('layouts.app') @section('content') <div class="container"> <h2>Edit Artikel</h2> @if ($errors->any()) <div class="alert alert-danger"> <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> @endif <form action="{{ route('artikel.update', $artikel->id) }}" method="POST"> @csrf @method('PUT') <div class="form-group"> <label for="judul">Judul:</label> <input type="text" class="form-control" id="judul" name="judul" value="{{ $artikel->judul }}" required> </div> <div class="form-group"> <label for="isi">Isi:</label> <textarea class="form-control" id="isi" name="isi" rows="5" required>{{ $artikel->isi }}</textarea> </div> <div class="form-group"> <label for="tanggal_terbit">Tanggal Terbit:</label> <input type="date" class="form-control" id="tanggal_terbit" name="tanggal_terbit" value="{{ $artikel->tanggal_terbit ? $artikel->tanggal_terbit->format('Y-m-d') : '' }}"> </div> <button type="submit" class="btn btn-primary">Perbarui</button> <a href="{{ route('artikel.index') }}" class="btn btn-secondary">Batal</a> </form> </div> @endsection
-
Buat Layout Dasar (
resources/views/layouts/app.blade.php
): Ini akan berisi struktur HTML dasar, termasuk CSS, JavaScript, dan navigasi. Kamu bisa menggunakan Bootstrap untuk styling yang lebih cepat.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>CRUD Artikel Laravel 9</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
@yield('content')
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
Penjelasan Views:
- Semua views menggunakan
@extends('layouts.app')
untuk mewarisi layout dasar dariresources/views/layouts/app.blade.php
. @section('content')
dan@endsection
mendefinisikan bagian content yang akan diisi oleh masing-masing view.{{ route('artikel.index') }}
menghasilkan URL untuk routeartikel.index
.{{ $artikel->judul }}
menampilkan nilai dari propertijudul
pada object$artikel
.@csrf
menambahkan token CSRF untuk melindungi form dari serangan CSRF.@method('PUT')
atau@method('DELETE')
digunakan untuk mengoverride method HTTP form menjadi PUT atau DELETE (karena HTML form hanya mendukung GET dan POST).@if ($errors->any())
digunakan untuk menampilkan pesan error validasi jika ada.old('judul')
digunakan untuk mempertahankan nilai input form jika validasi gagal.Str::limit($artikel->isi, 50)
digunakan untuk membatasi tampilan isi artikel agar tidak terlalu panjang di daftar artikel.$artikels->links()
menampilkan link paginasi.
8. Uji Aplikasi CRUD Kamu
Setelah semua kode selesai dibuat, jalankan server development Laravel dengan perintah:
php artisan serve
Buka browser dan akses http://localhost:8000/artikel
. Kamu seharusnya melihat daftar artikel (jika sudah ada), dan tombol untuk membuat artikel baru. Coba semua operasi CRUD: membuat, membaca, memperbarui, dan menghapus artikel.
9. Validasi dan Keamanan Tambahan
- Validasi Data: Pastikan kamu selalu memvalidasi data yang masuk dari form. Gunakan
$request->validate()
di controller untuk memastikan data sesuai dengan yang diharapkan. Contoh validasi sudah ada di metodestore
danupdate
padaArtikelController.php
. - Otorisasi: Jika aplikasi kamu membutuhkan otorisasi (misalnya, hanya admin yang boleh menghapus artikel), kamu bisa menggunakan middleware
auth
atau membuat kebijakan otorisasi (policies). - Escaping Data: Saat menampilkan data di views, gunakan sintaks
{{ $data }}
untuk secara otomatis melakukan escaping terhadap karakter-karakter khusus HTML, sehingga mencegah serangan XSS. - CSRF Protection: Pastikan semua form menggunakan
@csrf
untuk melindungi dari serangan CSRF.
10. Kesimpulan dan Langkah Selanjutnya
Selamat! Kamu telah berhasil membuat CRUD sederhana dengan Laravel 9. Tutorial ini memberikan dasar yang kuat untuk mengembangkan aplikasi web yang lebih kompleks. Selanjutnya, kamu bisa mempelajari:
- Relasi Database: Bagaimana menghubungkan tabel-tabel yang berbeda (misalnya, artikel dengan penulis).
- Autentikasi dan Otorisasi: Bagaimana mengelola pengguna dan memberikan hak akses yang berbeda.
- Testing: Bagaimana menulis unit tests dan feature tests untuk memastikan kode kamu berfungsi dengan benar.
- Deployment: Bagaimana menyebarkan aplikasi kamu ke server production.
- Penggunaan Library Tambahan: Pelajari package Laravel yang dapat membantu mempermudah development, seperti Sanctum untuk autentikasi API atau Livewire untuk membuat interface yang interaktif.
Semoga tutorial ini bermanfaat! Selamat mencoba dan terus belajar!