Laravel 9, framework PHP yang populer, menawarkan cara yang elegan dan efisien untuk membangun aplikasi web. Salah satu fondasi dari banyak aplikasi web adalah kemampuan untuk melakukan operasi CRUD (Create, Read, Update, Delete) pada data. Dalam tutorial ini, kita akan mempelajari secara mendalam cara Membuat CRUD dengan Laravel 9 dan MySQL secara step-by-step. Jadi, siapkan kopi Anda, buka editor kode Anda, dan mari kita mulai!
1. Persiapan Awal: Instalasi Laravel 9 dan Konfigurasi Database MySQL
Sebelum kita menyelam ke dalam kode, pastikan Anda memiliki semua yang diperlukan. Ini meliputi:
- PHP: Versi 8.0 atau lebih tinggi. Anda dapat memeriksa versi PHP Anda dengan perintah
php -vdi terminal. - Composer: Dependency manager untuk PHP. Unduh dan instal dari https://getcomposer.org/.
- MySQL: Database relasional yang akan kita gunakan. Pastikan server MySQL Anda berjalan.
- Node.js dan npm: Untuk mengelola aset front-end (opsional, tetapi disarankan).
Setelah Anda memastikan semua persyaratan terpenuhi, mari kita instal Laravel 9:
-
Buka terminal atau command prompt.
-
Navigasikan ke direktori tempat Anda ingin menyimpan proyek Laravel Anda.
-
Jalankan perintah berikut:
composer create-project laravel/laravel crud-appGanti
crud-appdengan nama proyek yang Anda inginkan.
Setelah instalasi selesai, masuk ke direktori proyek:
cd crud-app
Selanjutnya, kita perlu mengkonfigurasi koneksi ke database MySQL kita. Buka file .env di root proyek Anda. Cari bagian yang terkait dengan database:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=
Ubah nilai-nilai ini sesuai dengan konfigurasi database MySQL Anda.
DB_DATABASE: Nama database yang akan kita gunakan. Pastikan database ini sudah dibuat di server MySQL Anda.DB_USERNAME: Username untuk mengakses database.DB_PASSWORD: Password untuk mengakses database.
Setelah konfigurasi database selesai, jalankan perintah berikut untuk membuat key aplikasi Laravel:
php artisan key:generate
2. Membuat Model dan Migrasi: Struktur Tabel Database
Langkah selanjutnya adalah mendefinisikan struktur tabel database yang akan kita gunakan untuk menyimpan data. Kita akan menggunakan model dan migrasi Laravel untuk mempermudah proses ini. Mari kita asumsikan kita akan membuat CRUD untuk data “Produk”.
Gunakan perintah Artisan untuk membuat model dan migrasi secara bersamaan:
php artisan make:model Product -m
Perintah ini akan membuat dua file:
app/Models/Product.php: ModelProductyang merepresentasikan tabelproductsdi database.database/migrations/[timestamp]_create_products_table.php: File migrasi yang akan digunakan untuk membuat tabelproducts.
Buka file migrasi yang baru dibuat. Anda akan melihat struktur dasar untuk membuat tabel. Modifikasi file tersebut untuk menambahkan kolom-kolom yang Anda butuhkan untuk menyimpan data produk. Misalnya:
<?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->integer('stock');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('products');
}
};
Kode di atas mendefinisikan tabel products dengan kolom-kolom berikut:
id: Primary key (otomatis dibuat oleh Laravel).name: Nama produk (string).description: Deskripsi produk (teks, opsional).price: Harga produk (desimal).stock: Stok produk (integer).created_atdanupdated_at: Kolom timestamps (otomatis dibuat oleh Laravel).
Setelah mendefinisikan struktur tabel, jalankan migrasi untuk membuat tabel di database:
php artisan migrate
3. Membuat Controller: Logika Aplikasi CRUD Produk
Controller akan menjadi pusat logika untuk operasi CRUD kita. Kita akan membuat controller ProductController untuk menangani semua permintaan terkait produk.
Gunakan perintah Artisan untuk membuat controller:
php artisan make:controller ProductController
Ini akan membuat file app/Http/Controllers/ProductController.php.
Sekarang, mari kita tambahkan method-method untuk menangani operasi CRUD:
<?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(); // Mengambil semua produk dari database
return view('products.index', compact('products')); // Menampilkan view dengan data produk
}
/**
* Show the form for creating a new resource.
*
* @return IlluminateHttpResponse
*/
public function create()
{
return view('products.create'); // Menampilkan form untuk membuat produk baru
}
/**
* Store a newly created resource in storage.
*
* @param IlluminateHttpRequest $request
* @return IlluminateHttpResponse
*/
public function store(Request $request)
{
$request->validate([
'name' => 'required',
'description' => 'nullable',
'price' => 'required|numeric',
'stock' => 'required|integer',
]);
Product::create($request->all()); // Membuat produk baru di database
return redirect()->route('products.index')
->with('success', 'Produk berhasil ditambahkan.');
}
/**
* Display the specified resource.
*
* @param AppModelsProduct $product
* @return IlluminateHttpResponse
*/
public function show(Product $product)
{
return view('products.show', compact('product')); // Menampilkan detail produk
}
/**
* Show the form for editing the specified resource.
*
* @param AppModelsProduct $product
* @return IlluminateHttpResponse
*/
public function edit(Product $product)
{
return view('products.edit', compact('product')); // Menampilkan form untuk mengedit produk
}
/**
* 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',
'description' => 'nullable',
'price' => 'required|numeric',
'stock' => 'required|integer',
]);
$product->update($request->all()); // Mengupdate data produk di database
return redirect()->route('products.index')
->with('success', 'Produk berhasil diupdate.');
}
/**
* Remove the specified resource from storage.
*
* @param AppModelsProduct $product
* @return IlluminateHttpResponse
*/
public function destroy(Product $product)
{
$product->delete(); // Menghapus produk dari database
return redirect()->route('products.index')
->with('success', 'Produk berhasil dihapus.');
}
}
Controller ini memiliki method-method berikut:
index(): Menampilkan daftar semua produk.create(): Menampilkan form untuk membuat produk baru.store(Request $request): Menyimpan produk baru ke database.show(Product $product): Menampilkan detail produk.edit(Product $product): Menampilkan form untuk mengedit produk.update(Request $request, Product $product): Mengupdate data produk di database.destroy(Product $product): Menghapus produk dari database.
Perhatikan penggunaan Request $request untuk menangani data yang dikirimkan melalui form, dan validasi data menggunakan $request->validate(). Ini adalah praktik yang baik untuk memastikan data yang masuk valid dan aman.
4. Membuat Routes: Menghubungkan URL ke Controller
Sekarang kita memiliki controller, kita perlu mendefinisikan routes untuk menghubungkan URL ke method-method controller kita. Buka file routes/web.php.
Gunakan resource controller routing untuk mempermudah:
<?php
use AppHttpControllersProductController;
use IlluminateSupportFacadesRoute;
/*
|--------------------------------------------------------------------------
| 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);
Route::resource('products', ProductController::class) secara otomatis mendefinisikan routes untuk semua operasi CRUD yang umum, seperti:
GET /products:ProductController@indexGET /products/create:ProductController@createPOST /products:ProductController@storeGET /products/{product}:ProductController@showGET /products/{product}/edit:ProductController@editPUT /products/{product}atauPATCH /products/{product}:ProductController@updateDELETE /products/{product}:ProductController@destroy
5. Membuat Views: Menampilkan Data dan Form
Kita perlu membuat views untuk menampilkan data produk dan form untuk membuat dan mengedit produk. Buat direktori resources/views/products dan buat file-file berikut:
resources/views/products/index.blade.php: Menampilkan daftar produk.resources/views/products/create.blade.php: Form untuk membuat produk baru.resources/views/products/show.blade.php: Menampilkan detail produk.resources/views/products/edit.blade.php: Form untuk mengedit produk.
resources/views/products/index.blade.php:
<!DOCTYPE html>
<html>
<head>
<title>Daftar Produk</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<h1>Daftar Produk</h1>
@if ($message = Session::get('success'))
<div class="alert alert-success">
<p>{{ $message }}</p>
</div>
@endif
<a class="btn btn-success" href="{{ route('products.create') }}"> Tambah Produk Baru</a>
<table class="table table-bordered">
<tr>
<th>No</th>
<th>Nama</th>
<th>Harga</th>
<th>Stok</th>
<th width="280px">Aksi</th>
</tr>
@foreach ($products as $product)
<tr>
<td>{{ ++$i }}</td>
<td>{{ $product->name }}</td>
<td>{{ $product->price }}</td>
<td>{{ $product->stock }}</td>
<td>
<form action="{{ route('products.destroy',$product->id) }}" method="POST">
<a class="btn btn-info" href="{{ route('products.show',$product->id) }}">Lihat</a>
<a class="btn btn-primary" href="{{ route('products.edit',$product->id) }}">Edit</a>
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger">Hapus</button>
</form>
</td>
</tr>
@endforeach
</table>
{!! $products->links() !!}
</div>
</body>
</html>
resources/views/products/create.blade.php:
<!DOCTYPE html>
<html>
<head>
<title>Tambah Produk Baru</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<h1>Tambah Produk Baru</h1>
@if ($errors->any())
<div class="alert alert-danger">
<strong>Whoops!</strong> Ada kesalahan saat input data.<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>Nama:</strong>
<input type="text" name="name" class="form-control" placeholder="Nama">
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>Deskripsi:</strong>
<textarea class="form-control" style="height:150px" name="description" placeholder="Deskripsi"></textarea>
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>Harga:</strong>
<input type="number" step="0.01" name="price" class="form-control" placeholder="Harga">
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>Stok:</strong>
<input type="number" name="stock" class="form-control" placeholder="Stok">
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12 text-center">
<button type="submit" class="btn btn-primary">Simpan</button>
</div>
</div>
</form>
</div>
</body>
</html>
resources/views/products/show.blade.php:
<!DOCTYPE html>
<html>
<head>
<title>Detail Produk</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<h1>Detail Produk</h1>
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>Nama:</strong>
{{ $product->name }}
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>Deskripsi:</strong>
{{ $product->description }}
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>Harga:</strong>
{{ $product->price }}
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>Stok:</strong>
{{ $product->stock }}
</div>
</div>
</div>
</div>
</body>
</html>
resources/views/products/edit.blade.php:
<!DOCTYPE html>
<html>
<head>
<title>Edit Produk</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<h1>Edit Produk</h1>
@if ($errors->any())
<div class="alert alert-danger">
<strong>Whoops!</strong> Ada kesalahan saat input data.<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>Nama:</strong>
<input type="text" name="name" value="{{ $product->name }}" class="form-control" placeholder="Nama">
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>Deskripsi:</strong>
<textarea class="form-control" style="height:150px" name="description" placeholder="Deskripsi">{{ $product->description }}</textarea>
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>Harga:</strong>
<input type="number" step="0.01" name="price" value="{{ $product->price }}" class="form-control" placeholder="Harga">
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>Stok:</strong>
<input type="number" name="stock" value="{{ $product->stock }}" class="form-control" placeholder="Stok">
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12 text-center">
<button type="submit" class="btn btn-primary">Update</button>
</div>
</div>
</form>
</div>
</body>
</html>
Pastikan untuk menyesuaikan tampilan dan field form sesuai dengan kebutuhan aplikasi Anda. Jangan lupa tambahkan styling CSS agar tampilan lebih menarik. Anda bisa menggunakan Bootstrap seperti contoh di atas.
6. Uji Coba CRUD: Memastikan Aplikasi Berjalan Lancar
Setelah semua langkah di atas selesai, saatnya untuk menguji aplikasi CRUD kita.
-
Jalankan server pengembangan Laravel:
php artisan serve -
Buka browser Anda dan kunjungi
http://localhost:8000/products.
Anda akan melihat daftar produk (jika ada). Anda dapat menambahkan produk baru, mengedit, menghapus, dan melihat detail produk. Pastikan semua operasi CRUD berjalan dengan lancar dan sesuai dengan harapan.
7. Validasi Lebih Lanjut dan Error Handling yang Robust
Validasi data adalah bagian penting dari pengembangan aplikasi. Kita sudah menggunakan validasi sederhana di ProductController, tetapi kita bisa meningkatkan validasi ini lebih lanjut.
Custom Request:
Anda dapat membuat custom request untuk validasi yang lebih kompleks. Gunakan perintah Artisan:
php artisan make:request StoreProductRequest
Ini akan membuat file app/Http/Requests/StoreProductRequest.php. Di dalam file ini, Anda dapat mendefinisikan aturan validasi yang lebih spesifik:
<?php
namespace AppHttpRequests;
use IlluminateFoundationHttpFormRequest;
class StoreProductRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true; // Atau logika otorisasi yang sesuai
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
return [
'name' => 'required|string|max:255',
'description' => 'nullable|string',
'price' => 'required|numeric|min:0.01',
'stock' => 'required|integer|min:0',
];
}
}
Kemudian, gunakan StoreProductRequest di ProductController:
public function store(StoreProductRequest $request)
{
Product::create($request->validated());
return redirect()->route('products.index')
->with('success', 'Produk berhasil ditambahkan.');
}
Error Handling:
Pastikan untuk menangani error dengan baik. Gunakan try-catch blocks untuk menangkap exceptions yang mungkin terjadi, dan tampilkan pesan error yang informatif kepada pengguna.
8. Menggunakan Eloquent ORM: Interaksi Database yang Mudah
Eloquent ORM adalah fitur powerful di Laravel yang memungkinkan kita untuk berinteraksi dengan database menggunakan objek PHP. Kita sudah menggunakan Eloquent untuk mengambil dan menyimpan data. Mari kita lihat beberapa contoh lagi.
Query Scopes:
Anda dapat mendefinisikan query scopes di model Product untuk membuat query yang reusable. Misalnya, kita bisa membuat scope untuk mengambil produk dengan stok di atas 0:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;
class Product extends Model
{
use HasFactory;
protected $fillable = [
'name',
'description',
'price',
'stock',
];
public function scopeAvailable($query)
{
return $query->where('stock', '>', 0);
}
}
Kemudian, Anda dapat menggunakan scope ini di controller:
public function index()
{
$products = Product::available()->get();
return view('products.index', compact('products'));
}
Relationships:
Jika Anda memiliki tabel lain yang berhubungan dengan tabel products, Anda dapat mendefinisikan relationships di model. Misalnya, jika Anda memiliki tabel categories, Anda dapat mendefinisikan relationship belongsTo di model Product:
public function category()
{
return $this->belongsTo(Category::class);
}
9. Keamanan Aplikasi CRUD: Melindungi Data Sensitif
Keamanan adalah aspek penting dalam pengembangan aplikasi. Pastikan untuk melindungi aplikasi CRUD Anda dari serangan yang umum.
CSRF Protection:
Laravel secara otomatis menyediakan CSRF (Cross-Site Request Forgery) protection. Pastikan Anda menyertakan @csrf di semua form Anda.
XSS Protection:
Lindungi aplikasi Anda dari XSS (Cross-Site Scripting) attacks dengan melakukan escaping terhadap data yang ditampilkan di views. Gunakan kurung kurawal ganda {{ $data }} untuk melakukan escaping otomatis.
Authorization:
Tentukan siapa yang berhak mengakses dan memodifikasi data. Gunakan policies Laravel untuk mengontrol akses berdasarkan role atau permission.
10. Pagination dan Sorting: Manajemen Data yang Efisien
Jika Anda memiliki banyak data, pagination dan sorting akan membuat manajemen data menjadi lebih efisien.
Pagination:
Laravel menyediakan pagination yang mudah digunakan. Di controller, gunakan method paginate() untuk mengambil data dengan pagination:
public function index()
{
$products = Product::paginate(10); // Menampilkan 10 produk per halaman
return view('products.index', compact('products'));
}
Kemudian, di view, gunakan method links() untuk menampilkan link pagination:
{!! $products->links() !!}
Sorting:
Anda dapat menambahkan fungsionalitas sorting ke daftar produk Anda. Tambahkan link ke kolom yang ingin Anda gunakan untuk sorting, dan kirimkan parameter sort dan direction melalui URL. Di controller, gunakan parameter ini untuk mengurutkan data:
public function index(Request $request)
{
$sort = $request->input('sort', 'name'); // Default sorting berdasarkan nama
$direction = $request->input('direction', 'asc'); // Default direction ascending
$products = Product::orderBy($sort, $direction)->paginate(10);
return view('products.index', compact('products', 'sort', 'direction'));
}
11. Penerapan Unit Testing: Memastikan Kode Berfungsi Dengan Baik
Unit testing adalah praktik penting untuk memastikan kode yang Anda tulis berfungsi dengan baik dan menghindari bug. Laravel menyediakan dukungan bawaan untuk unit testing dengan PHPUnit.
Membuat Test:
Gunakan perintah Artisan untuk membuat test case baru:
php artisan make:test ProductControllerTest
Ini akan membuat file tests/Feature/ProductControllerTest.php.
Menulis Test:
Di dalam test case, Anda dapat menulis test untuk menguji berbagai aspek dari ProductController. Misalnya, kita bisa membuat test untuk memastikan bahwa method index menampilkan daftar produk:
<?php
namespace TestsFeature;
use AppModelsProduct;
use IlluminateFoundationTestingRefreshDatabase;
use IlluminateFoundationTestingWithFaker;
use TestsTestCase;
class ProductControllerTest extends TestCase
{
use RefreshDatabase;
/**
* A basic feature test example.
*
* @return void
*/
public function test_index_returns_a_successful_response()
{
Product::factory()->count(3)->create(); // Membuat 3 produk dummy
$response = $this->get('/products');
$response->assertStatus(200);
$response->assertViewIs('products.index');
$response->assertViewHas('products');
}
}
Menjalankan Test:
Jalankan test menggunakan perintah Artisan:
php artisan test
12. Deployment ke Server: Mengakses Aplikasi dari Internet
Setelah aplikasi CRUD Anda selesai dan diuji, saatnya untuk melakukan deployment ke server agar dapat diakses dari internet. Proses deployment dapat bervariasi tergantung pada server dan platform yang Anda gunakan.
Beberapa opsi deployment:
- Shared Hosting: Opsi yang paling sederhana dan terjangkau.
- VPS (Virtual Private Server): Memberikan kontrol lebih besar terhadap server Anda.
- Cloud Platforms (AWS, Google Cloud, Azure): Memberikan skalabilitas dan fleksibilitas.
- Laravel Vapor: Platform deployment yang dirancang khusus untuk aplikasi Laravel.
Langkah-langkah Umum Deployment:
- Konfigurasi Server: Pastikan server Anda memenuhi persyaratan Laravel 9 (PHP 8.0+, MySQL, dll.).
- Transfer Kode: Unggah kode aplikasi Anda ke server.
- Konfigurasi Database: Konfigurasi koneksi database di server (file
.env). - Instal Dependencies: Jalankan
composer installdi server. - Migrate Database: Jalankan
php artisan migratedi server. - Konfigurasi Web Server (Nginx/Apache): Konfigurasi web server untuk mengarahkan traffic ke aplikasi Laravel Anda.
- Set Application Key: Jalankan
php artisan key:generatedi server (jika belum dilakukan). - Optimasi: Lakukan optimasi seperti caching dan kompresi aset.
Tips Deployment:
- Gunakan sistem kontrol versi (Git) untuk mempermudah deployment dan rollback.
- Otomatiskan proses deployment menggunakan tools seperti Deployer atau Envoyer.
- Monitor aplikasi Anda setelah deployment untuk memastikan tidak ada masalah.
Dengan mengikuti tutorial step-by-step ini, Anda seharusnya sekarang memiliki pemahaman yang baik tentang cara Membuat CRUD dengan Laravel 9 dan MySQL. Ingatlah untuk selalu memprioritaskan keamanan, validasi data, dan pengujian untuk menghasilkan aplikasi yang berkualitas tinggi. Selamat mencoba dan semoga sukses!



