Laravel 9 adalah framework PHP yang populer dan kuat, sangat cocok untuk membangun aplikasi web modern. Salah satu fondasi dari banyak aplikasi web adalah kemampuan untuk melakukan operasi CRUD (Create, Read, Update, Delete). Artikel ini akan memberikan panduan praktis langkah demi langkah tentang cara membuat CRUD dengan Laravel 9, mulai dari persiapan hingga implementasi lengkap. Siapkan kopi atau teh Anda, mari kita mulai!
1. Persiapan Awal: Memastikan Lingkungan Pengembangan Laravel 9 Siap
Sebelum kita mulai membangun CRUD, pastikan Anda sudah memiliki lingkungan pengembangan yang siap. Ini mencakup beberapa hal penting:
- PHP: Pastikan Anda memiliki PHP versi 8.0 atau lebih tinggi. Laravel 9 membutuhkan PHP versi ini. Anda bisa memeriksa versi PHP Anda dengan perintah
php -v
di terminal. - Composer: Composer adalah package manager untuk PHP. Anda akan membutuhkannya untuk menginstal Laravel dan dependensi lainnya. Anda bisa mengunduh dan menginstal Composer dari https://getcomposer.org/.
- Database: Anda memerlukan database. Dalam contoh ini, kita akan menggunakan MySQL. Pastikan MySQL sudah terinstal dan berjalan di sistem Anda. Anda juga bisa menggunakan database lain seperti PostgreSQL atau SQLite.
- Node.js dan NPM (Optional): Meskipun tidak mutlak diperlukan untuk CRUD dasar, Node.js dan NPM berguna untuk mengelola asset frontend seperti JavaScript dan CSS. Jika Anda berencana menggunakan Laravel Mix, Anda akan membutuhkannya. Anda bisa mengunduh dan menginstal Node.js dari https://nodejs.org/.
- Editor Kode: Pilih editor kode favorit Anda. Visual Studio Code, Sublime Text, atau PhpStorm adalah pilihan populer.
Setelah semua persiapan ini selesai, kita siap untuk membuat proyek Laravel 9 baru.
2. Membuat Proyek Laravel 9 Baru: Langkah Pertama Membangun CRUD
Untuk memulai, buka terminal Anda dan jalankan perintah berikut untuk membuat proyek Laravel 9 baru:
composer create-project laravel/laravel crud_app
cd crud_app
Perintah ini akan membuat direktori baru bernama crud_app
(Anda bisa menggantinya dengan nama yang Anda inginkan) dan menginstal Laravel 9 di dalamnya. Setelah proses instalasi selesai, masuk ke direktori proyek dengan perintah cd crud_app
.
Selanjutnya, kita perlu mengkonfigurasi koneksi database. Buka file .env
di root proyek Anda. Cari bagian yang berkaitan dengan konfigurasi database (mulai dengan DB_
). Ubah nilai-nilai berikut sesuai dengan pengaturan database Anda:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=nama_database_anda
DB_USERNAME=nama_pengguna_database
DB_PASSWORD=password_database_anda
Pastikan nama_database_anda
, nama_pengguna_database
, dan password_database_anda
sesuai dengan konfigurasi database Anda. Jika Anda belum membuat database, buatlah sekarang menggunakan alat seperti phpMyAdmin atau perintah SQL.
3. Membuat Model dan Migrasi: Fondasi Data CRUD
Setelah proyek dibuat dan konfigurasi database selesai, langkah selanjutnya adalah membuat model dan migrasi. Model akan merepresentasikan data yang akan kita kelola, dan migrasi akan digunakan untuk membuat tabel yang sesuai di database.
Misalkan kita ingin membuat CRUD untuk mengelola data Product
(Produk). Jalankan perintah berikut di terminal:
php artisan make:model Product -m
Perintah ini akan membuat dua file:
app/Models/Product.php
: File modelProduct
.database/migrations/yyyy_mm_dd_hhmmss_create_products_table.php
: File migrasi untuk membuat tabelproducts
.
Buka file migrasi database/migrations/yyyy_mm_dd_hhmmss_create_products_table.php
dan modifikasi method up()
untuk mendefinisikan struktur tabel products
. Contohnya:
<?php
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->text('description')->nullable();
$table->decimal('price', 10, 2);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('products');
}
};
Kode di atas akan membuat tabel products
dengan kolom id
, name
, description
, price
, created_at
, dan updated_at
. name
adalah nama produk, description
adalah deskripsi produk (boleh kosong), dan price
adalah harga produk.
Setelah memodifikasi file migrasi, jalankan migrasi untuk membuat tabel di database:
php artisan migrate
Perintah ini akan menjalankan semua migrasi yang tertunda, termasuk migrasi yang baru saja kita buat.
Selanjutnya, buka file model app/Models/Product.php
dan tambahkan kode berikut untuk menentukan properti $fillable
:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;
class Product extends Model
{
use HasFactory;
protected $fillable = [
'name',
'description',
'price',
];
}
Properti $fillable
menentukan kolom mana yang boleh diisi secara massal (mass assignment) saat membuat atau memperbarui data. Ini adalah praktik keamanan penting untuk mencegah kerentanan mass assignment.
4. Membuat Controller: Menangani Logika Bisnis CRUD
Controller bertanggung jawab untuk menangani logika bisnis CRUD. Kita akan membuat controller ProductController
untuk mengelola data Product
. Jalankan perintah berikut di terminal:
php artisan make:controller ProductController --resource
Opsi --resource
akan membuat controller dengan method-method standar untuk operasi CRUD: index
, create
, store
, show
, edit
, update
, dan destroy
.
Buka file app/Http/Controllers/ProductController.php
dan implementasikan masing-masing method:
<?php
namespace AppHttpControllers;
use AppModelsProduct;
use IlluminateHttpRequest;
class ProductController extends Controller
{
/**
* Display a listing of the resource.
*
* @return IlluminateHttpResponse
*/
public function index()
{
$products = Product::all();
return view('products.index', compact('products'));
}
/**
* Show the form for creating a new resource.
*
* @return IlluminateHttpResponse
*/
public function create()
{
return view('products.create');
}
/**
* Store a newly created resource in storage.
*
* @param IlluminateHttpRequest $request
* @return IlluminateHttpResponse
*/
public function store(Request $request)
{
$request->validate([
'name' => 'required',
'price' => 'required|numeric',
]);
Product::create($request->all());
return redirect()->route('products.index')
->with('success','Product created successfully.');
}
/**
* Display the specified resource.
*
* @param AppModelsProduct $product
* @return IlluminateHttpResponse
*/
public function show(Product $product)
{
return view('products.show',compact('product'));
}
/**
* Show the form for editing the specified resource.
*
* @param AppModelsProduct $product
* @return IlluminateHttpResponse
*/
public function edit(Product $product)
{
return view('products.edit',compact('product'));
}
/**
* Update the specified resource in storage.
*
* @param IlluminateHttpRequest $request
* @param AppModelsProduct $product
* @return IlluminateHttpResponse
*/
public function update(Request $request, Product $product)
{
$request->validate([
'name' => 'required',
'price' => 'required|numeric',
]);
$product->update($request->all());
return redirect()->route('products.index')
->with('success','Product updated successfully');
}
/**
* Remove the specified resource from storage.
*
* @param AppModelsProduct $product
* @return IlluminateHttpResponse
*/
public function destroy(Product $product)
{
$product->delete();
return redirect()->route('products.index')
->with('success','Product deleted successfully');
}
}
Mari kita bahas setiap method:
index()
: Mengambil semua dataProduct
dari database dan menampilkannya di viewproducts.index
.create()
: Menampilkan form untuk membuat dataProduct
baru (viewproducts.create
).store(Request $request)
: Menyimpan dataProduct
baru ke database. Melakukan validasi input terlebih dahulu.show(Product $product)
: Menampilkan detail dataProduct
tertentu (viewproducts.show
).edit(Product $product)
: Menampilkan form untuk mengedit dataProduct
tertentu (viewproducts.edit
).update(Request $request, Product $product)
: Memperbarui dataProduct
tertentu di database. Melakukan validasi input terlebih dahulu.destroy(Product $product)
: Menghapus dataProduct
tertentu dari database.
Perhatikan penggunaan Product::all()
, Product::create()
, $product->update()
, dan $product->delete()
untuk melakukan operasi CRUD dengan model Product
.
5. Membuat Views: Menampilkan Data dan Form CRUD
Views adalah tampilan antarmuka pengguna yang ditampilkan kepada pengguna. Kita perlu membuat views untuk menampilkan daftar produk, form untuk membuat dan mengedit produk, serta detail produk.
Buat direktori resources/views/products
. Di dalam direktori ini, buat file-file berikut:
index.blade.php
: Menampilkan daftar produk.create.blade.php
: Menampilkan form untuk membuat produk baru.show.blade.php
: Menampilkan detail produk.edit.blade.php
: Menampilkan form untuk mengedit produk.
Berikut adalah contoh isi dari masing-masing file:
index.blade.php
:
<!DOCTYPE html>
<html>
<head>
<title>Products</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
@if ($message = Session::get('success'))
<div class="alert alert-success">
<p>{{ $message }}</p>
</div>
@endif
<div class="row">
<div class="col-lg-12 margin-tb">
<div class="pull-left">
<h2>Products</h2>
</div>
<div class="pull-right">
<a class="btn btn-success" href="{{ route('products.create') }}"> Create New Product</a>
</div>
</div>
</div>
<table class="table table-bordered">
<tr>
<th>ID</th>
<th>Name</th>
<th>Description</th>
<th>Price</th>
<th width="280px">Action</th>
</tr>
@foreach ($products as $product)
<tr>
<td>{{ $product->id }}</td>
<td>{{ $product->name }}</td>
<td>{{ $product->description }}</td>
<td>{{ $product->price }}</td>
<td>
<form action="{{ route('products.destroy',$product->id) }}" method="POST">
<a class="btn btn-info" href="{{ route('products.show',$product->id) }}">Show</a>
<a class="btn btn-primary" href="{{ route('products.edit',$product->id) }}">Edit</a>
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
@endforeach
</table>
</div>
</body>
</html>
create.blade.php
:
<!DOCTYPE html>
<html>
<head>
<title>Create New Product</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-lg-12 margin-tb">
<div class="pull-left">
<h2>Add New Product</h2>
</div>
<div class="pull-right">
<a class="btn btn-primary" href="{{ route('products.index') }}"> Back</a>
</div>
</div>
</div>
@if ($errors->any())
<div class="alert alert-danger">
<strong>Whoops!</strong> There were some problems with your input.<br><br>
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form action="{{ route('products.store') }}" method="POST">
@csrf
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>Name:</strong>
<input type="text" name="name" class="form-control" placeholder="Name">
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>Description:</strong>
<textarea class="form-control" style="height:150px" name="description" placeholder="Description"></textarea>
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>Price:</strong>
<input type="number" step="0.01" name="price" class="form-control" placeholder="Price">
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12 text-center">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</div>
</form>
</div>
</body>
</html>
show.blade.php
:
<!DOCTYPE html>
<html>
<head>
<title>Show Product</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-lg-12 margin-tb">
<div class="pull-left">
<h2> Show Product</h2>
</div>
<div class="pull-right">
<a class="btn btn-primary" href="{{ route('products.index') }}"> Back</a>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>Name:</strong>
{{ $product->name }}
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>Description:</strong>
{{ $product->description }}
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>Price:</strong>
{{ $product->price }}
</div>
</div>
</div>
</div>
</body>
</html>
edit.blade.php
:
<!DOCTYPE html>
<html>
<head>
<title>Edit Product</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-lg-12 margin-tb">
<div class="pull-left">
<h2>Edit Product</h2>
</div>
<div class="pull-right">
<a class="btn btn-primary" href="{{ route('products.index') }}"> Back</a>
</div>
</div>
</div>
@if ($errors->any())
<div class="alert alert-danger">
<strong>Whoops!</strong> There were some problems with your input.<br><br>
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form action="{{ route('products.update',$product->id) }}" method="POST">
@csrf
@method('PUT')
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>Name:</strong>
<input type="text" name="name" value="{{ $product->name }}" class="form-control" placeholder="Name">
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>Description:</strong>
<textarea class="form-control" style="height:150px" name="description" placeholder="Description">{{ $product->description }}</textarea>
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>Price:</strong>
<input type="number" step="0.01" name="price" value="{{ $product->price }}" class="form-control" placeholder="Price">
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12 text-center">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</div>
</form>
</div>
</body>
</html>
Pastikan untuk menyesuaikan tampilan dan tata letak sesuai dengan kebutuhan aplikasi Anda. Kode di atas menggunakan Bootstrap untuk styling dasar. Anda dapat menggunakan framework CSS lain atau menulis CSS kustom Anda sendiri.
6. Mendefinisikan Rute: Menghubungkan URL ke Controller
Rute mendefinisikan bagaimana URL diakses dan controller mana yang akan menangani permintaan tersebut. Buka file routes/web.php
dan tambahkan rute berikut untuk ProductController
:
<?php
use IlluminateSupportFacadesRoute;
use AppHttpControllersProductController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', function () {
return view('welcome');
});
Route::resource('products', ProductController::class);
Baris Route::resource('products', ProductController::class);
akan otomatis membuat semua rute yang diperlukan untuk operasi CRUD pada ProductController
:
GET /products
: Menampilkan daftar produk (memanggil methodindex
).GET /products/create
: Menampilkan form untuk membuat produk baru (memanggil methodcreate
).POST /products
: Menyimpan produk baru (memanggil methodstore
).GET /products/{product}
: Menampilkan detail produk (memanggil methodshow
).GET /products/{product}/edit
: Menampilkan form untuk mengedit produk (memanggil methodedit
).PUT/PATCH /products/{product}
: Memperbarui produk (memanggil methodupdate
).DELETE /products/{product}
: Menghapus produk (memanggil methoddestroy
).
7. Uji Coba Aplikasi CRUD Laravel 9 Anda: Verifikasi Implementasi
Setelah semua langkah di atas selesai, Anda siap untuk menguji aplikasi CRUD Anda. Jalankan server pengembangan Laravel dengan perintah:
php artisan serve
Buka browser Anda dan akses http://localhost:8000/products
. Anda akan melihat tampilan daftar produk (yang saat ini kosong). Klik tombol “Create New Product” untuk membuat produk baru. Isi form dan klik “Submit”. Anda akan dikembalikan ke tampilan daftar produk dan melihat produk yang baru saja Anda buat.
Coba edit dan hapus produk. Pastikan semua operasi CRUD berfungsi dengan benar.
8. Validasi Input: Pentingnya Keamanan Data
Validasi input sangat penting untuk keamanan data. Pastikan Anda selalu melakukan validasi input sebelum menyimpan data ke database. Dalam contoh di atas, kita sudah melakukan validasi pada method store
dan update
di ProductController
:
$request->validate([
'name' => 'required',
'price' => 'required|numeric',
]);
Validasi ini memastikan bahwa kolom name
harus diisi dan kolom price
harus berupa angka. Anda dapat menambahkan aturan validasi lain sesuai dengan kebutuhan Anda. Anda bisa melihat dokumentasi validasi Laravel di https://laravel.com/docs/9.x/validation untuk informasi lebih lanjut.
9. Penggunaan Eloquent ORM: Mempermudah Interaksi Database
Laravel menggunakan Eloquent ORM (Object-Relational Mapper) untuk mempermudah interaksi dengan database. Eloquent menyediakan cara yang elegan dan mudah dibaca untuk melakukan operasi CRUD. Dalam contoh di atas, kita menggunakan Eloquent untuk:
- Mengambil semua data produk:
Product::all()
- Membuat produk baru:
Product::create($request->all())
- Memperbarui produk:
$product->update($request->all())
- Menghapus produk:
$product->delete()
Eloquent menyederhanakan proses interaksi database dan membuat kode Anda lebih mudah dibaca dan dipelihara.
10. Peningkatan CRUD dengan Fitur Tambahan: Pagination, Search, dan Lainnya
CRUD dasar hanyalah awal. Anda dapat meningkatkan aplikasi CRUD Anda dengan menambahkan fitur-fitur tambahan seperti:
- Pagination: Memecah daftar produk yang panjang menjadi halaman-halaman yang lebih kecil. Gunakan method
paginate()
pada model Eloquent. - Search: Memungkinkan pengguna mencari produk berdasarkan nama, deskripsi, atau kriteria lainnya. Gunakan query builder Eloquent untuk melakukan pencarian.
- Sort: Memungkinkan pengguna mengurutkan daftar produk berdasarkan kolom tertentu (misalnya, nama, harga).
- Upload Gambar: Memungkinkan pengguna mengunggah gambar untuk produk.
- Relasi Database: Jika produk memiliki relasi dengan tabel lain (misalnya, kategori), gunakan relasi Eloquent untuk mengelola data terkait.
11. Keamanan Aplikasi CRUD: Mencegah Serangan Potensial
Keamanan aplikasi CRUD sangat penting. Pastikan Anda mengambil langkah-langkah berikut untuk melindungi aplikasi Anda dari serangan potensial:
- Validasi Input: Selalu validasi semua input pengguna untuk mencegah serangan seperti SQL Injection dan Cross-Site Scripting (XSS).
- Otentikasi dan Otorisasi: Implementasikan otentikasi untuk memastikan hanya pengguna yang berwenang yang dapat mengakses fitur CRUD. Gunakan otorisasi untuk membatasi akses ke data dan fungsi berdasarkan peran pengguna.
- Proteksi CSRF: Laravel menyediakan proteksi CSRF (Cross-Site Request Forgery) secara default. Pastikan Anda mengaktifkannya di semua form Anda.
- Proteksi Mass Assignment: Gunakan properti
$fillable
atau$guarded
pada model Eloquent untuk mencegah kerentanan mass assignment. - Update Framework Secara Teratur: Selalu update Laravel ke versi terbaru untuk mendapatkan perbaikan keamanan terbaru.
12. Kesimpulan: CRUD Laravel 9, Landasan Aplikasi Web Modern
Selamat! Anda telah mempelajari cara membuat CRUD dengan Laravel 9 langkah demi langkah. Dari persiapan lingkungan pengembangan hingga implementasi controller, model, migrasi, views, dan rute, Anda sekarang memiliki pemahaman yang kuat tentang dasar-dasar membangun aplikasi CRUD dengan Laravel 9.
Ingatlah bahwa CRUD hanyalah fondasi. Teruslah belajar dan bereksperimen dengan fitur-fitur Laravel yang lebih canggih untuk membangun aplikasi web yang lebih kompleks dan kuat. Selamat berkarya! Semoga panduan cara membuat CRUD dengan Laravel 9 ini bermanfaat.