Tutorial ini akan membahas langkah demi langkah , mulai dari setup lingkungan pengembangan hingga membuat fitur lengkap untuk aplikasi Anda
Pada artikel ini, kita akan membahas Laravel CRUD Car Data, yaitu bagaimana mengelola data mobil dengan relasi ke tabel merk menggunakan framework Laravel. Proyek ini mencakup fitur Create, Read, Update, dan Delete serta implementasi relasi one-to-many antara mobil dan mer
Laravel saat ini menjadi salah satu framework PHP yang paling populer di kalangan web developer, terutama di Indonesia. Dengan fitur-fitur modern seperti routing yang simpel, ORM (Eloquent) yang powerful, dan ekosistem yang luas, tidak heran jika banyak orang ingin langsung lompat belajar Laravel untuk membangun web yang canggih dan profesional.
Tapi tunggu dulu. Sebelum kamu terlalu jauh menyelami Laravel, ada satu hal penting yang sering diabaikan oleh pemula: penguasaan dasar PHP. Laravel memang memudahkan banyak hal, tapi di balik kemudahannya itu, Laravel tetaplah framework yang dibangun dengan PHP. Artinya, jika kamu belum benar-benar memahami konsep dasar seperti variabel, array, loop, function, OOP (Object-Oriented Programming), dan lain-lain dalam PHP, kamu akan cepat merasa bingung atau bahkan stuck saat menggunakan Laravel.
Aku sendiri mengalami hal ini ketika pertama kali belajar Laravel. Tanpa bekal PHP yang cukup, banyak istilah dan fungsi yang terasa seperti “sulap”. Tapi setelah aku balik lagi ke dasar dan belajar PHP lebih dalam, segalanya mulai masuk akal kamu bisa belajar ke sini.
Di artikel ini, aku akan berbagi kenapa penting banget memahami PHP dulu sebelum lanjut ke Laravel, serta apa saja materi PHP yang wajib kamu kuasai. Yuk, kita mulai dari dasar agar langkahmu ke Laravel jadi lebih kuat dan terarah!
Siap! Berikut adalah versi panjang dan mengalir dari bagian yang kamu maksud, cocok untuk diletakkan setelah paragraf pembuka blog-mu:
Sebelum Mulai, Siapkan Dulu Alat Tempurnya
Sebelum kamu benar-benar masuk ke dunia Laravel, ada beberapa tools penting yang wajib kamu siapkan terlebih dahulu. Jangan langsung buru-buru belajar Laravel kalau belum meng-install tools ini, karena semuanya akan kamu butuhkan untuk menjalankan proyek Laravel dengan lancar.
1. PHP Versi 8 atau Lebih Baru
Laravel versi terbaru membutuhkan PHP minimal versi 8.2. Jadi, pastikan kamu sudah meng-install PHP dengan versi yang sesuai. Kamu bisa cek versi PHP yang terpasang di komputermu dengan menjalankan perintah berikut di terminal atau command prompt:
1 2 |
php -v |
Jika versinya masih di bawah 8, sebaiknya upgrade dulu agar nanti tidak ada error atau kendala saat install Laravel.
2. Composer
Composer adalah dependency manager untuk PHP, semacam “pengatur paket” yang akan kamu gunakan untuk meng-install Laravel dan semua library yang dibutuhkannya. Tanpa Composer, kamu nggak bisa install Laravel dengan cara resmi. Composer juga akan banyak kamu gunakan saat mengembangkan aplikasi Laravel.
Kamu bisa download Composer langsung dari situs resminya: https://getcomposer.org
Setelah terinstall, kamu bisa cek apakah Composer sudah aktif dengan perintah:
1 |
composer -v |
3. Node.js dan NPM
Kenapa Laravel butuh Node.js? Karena Laravel (khususnya fitur frontend seperti Vite, Livewire, atau saat pakai Tailwind CSS) memanfaatkan tools modern frontend yang berjalan di atas Node.js. Jadi, pastikan kamu sudah meng-install Node.js beserta npm (Node Package Manager).
Kamu bisa download dari: https://nodejs.org
Setelah terpasang, cek versinya:
1 2 |
node -v npm -v |
Kalau tools di atas sudah siap, kamu tinggal install Laravel dan mulai ngoding! Tapi ingat, sebelum langsung membuat project Laravel, pastikan kamu sudah nyaman dengan sintaks dan logika dasar PHP dulu, biar perjalanan belajarmu jadi lebih mulus. Kamu bisa klik ini
🧰 STEP 1 — Install Laravel
Setelah kamu memastikan PHP, Composer, dan Node.js sudah terinstall dengan benar di komputermu, sekarang saatnya kita masuk ke langkah inti: meng-install Laravel.
Laravel bisa kamu install dengan berbagai cara, tapi salah satu yang paling direkomendasikan dan mudah adalah menggunakan perintah composer create-project
.
📦 Jalankan Perintah Ini di Terminal atau CMD:
1 |
composer create-project laravel/laravel car_laravel |
Penjelasan:
composer create-project
: Ini adalah perintah untuk membuat project baru dengan Composer berdasarkan paket tertentu.-
laravel/laravel
: Ini adalah paket resmi dari Laravel, berisi struktur dasar dan semua dependensi Laravel. -
car_laravel
: Ini adalah nama folder/proyek kamu. Kamu bisa ganti dengan nama lain sesuai proyekmu, misalnyaweb_sekolah
,toko_online
, dll.
Setelah menjalankan perintah ini, Composer akan mengunduh semua file Laravel dan menyimpannya di folder car_laravel
.
📁 Pindah ke Folder Proyek:
1 |
cd car_laravel |
Perintah ini digunakan untuk masuk ke direktori proyek Laravel yang baru saja dibuat. Setelah berada di dalam folder tersebut, kamu bisa mulai menjalankan perintah-perintah Laravel lainnya, seperti menjalankan server lokal, membuat model, controller, dan sebagainya.
Proses install ini membutuhkan koneksi internet karena Composer akan mendownload berbagai dependensi Laravel dari repositori resmi. Jadi pastikan koneksi kamu stabil saat menjalankan perintah ini.
⚙️ STEP 2 — Configure .env
and Database
-
Setelah project Laravel berhasil dibuat, langsung aja kita sambungkan ke database.
📝 Edit File
.env
Buka file
.env
yang ada di folder project Laravel kamu, lalu temukan bagian pengaturan database dan ubah jadi seperti ini:
1 2 3 4 5 |
DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=laravel_car1 DB_USERNAME=root DB_PASSWORD= |
Pastikan kamu sudah nggak punya database
laravel_car1
di MySQL (pakai phpMyAdmin atau terminal),.
2. Run the migration di cmd/terminal kalian:
Setelah mengatur koneksi database di file .env
, sekarang kita jalankan perintah migration untuk membuat tabel-tabel default di database.
Buka terminal atau CMD kamu (pastikan posisinya sudah di dalam folder project Laravel), lalu ketik perintah berikut:
1 |
php artisan migrate |
Penjelasan singkat:
-
Perintah ini akan mengeksekusi semua file migration yang ada di folder
database/migrations
. -
Secara default, Laravel akan membuat beberapa tabel penting, seperti:
-
users
— untuk menyimpan data user -
password_resets
— untuk fitur reset password -
failed_jobs
— untuk mencatat job yang gagal -
personal_access_tokens
— untuk autentikasi API
-
Setelah berhasil dijalankan, kamu bisa cek ke phpMyAdmin atau database tool lainnya — tabel-tabel tersebut akan muncul secara otomatis di database yang kamu buat tadi.
Kalau muncul error saat migrate, pastikan koneksi database sudah benar dan database yang kamu tulis di
.env
memang sudah dibuat.
🏗️ STEP 3 — Create Model and Migration
Setelah berhasil melakukan migrate awal, sekarang saatnya kita membuat Model dan Migration khusus untuk data yang kita butuhkan di proyek ini. Dalam studi kasus ini, kita akan membuat dua entitas utama: Merk dan Car.
1 2 |
php artisan make:model Merk -m php artisan make:model Car -m |
Penjelasan:
-
php artisan make:model Merk -m
Perintah ini akan:-
Membuat file model
Merk.php
di folderapp/Models/
-
Membuat file migration
create_merks_table.php
di folderdatabase/migrations/
-
-
php artisan make:model Car -m
Sama seperti di atas, perintah ini akan:-
Membuat file model
Car.php
-
Dan migration untuk tabel
cars
-
Flag -m
di sini artinya sekalian buat file migration-nya. Jadi kita tidak perlu buat secara terpisah, lebih efisien
🛠️ Edit File Migration create_merks_table.php
Setelah menjalankan perintah:
1 |
php artisan make:model Merk -m |
Laravel akan otomatis membuat file migration untuk tabel merks
di folder:
1 |
database/migrations/ |
Buka file tersebut (namanya biasanya diawali dengan xxxx_xx_xx_create_merks_table.php
), lalu ubah method up()
jadi seperti ini:
1 2 3 4 5 |
Schema::create('merks', function (Blueprint $table) { $table->id(); $table->string('name'); $table->timestamps(); }); |
🧾 Penjelasan Struktur Tabel:
-
$table->id();
Membuat kolomid
(auto increment) sebagai primary key. -
$table->string('name');
Untuk menyimpan nama merk mobil, misalnya: Toyota, Honda, Suzuki, dll. -
$table->timestamps();
Menambahkan dua kolom otomatis:-
created_at
→ waktu data dibuat -
updated_at
→ waktu data terakhir diperbaru
-
Edit create_cars_table.php
Setelah kamu menjalankan:
1 |
php artisan make:model Car -m |
Laravel akan membuat file migration untuk tabel
cars
. Sekarang buka file migration tersebut (biasanya diawali dengan nama seperti xxxx_xx_xx_create_cars_table.php
), lalu ubah isi method up()
menjadi seperti ini:
1 2 3 4 5 6 7 8 9 10 |
Schema::create('cars', function (Blueprint $table) { $table->id(); $table->foreignId('merk_id')->constrained('merks')->onDelete('cascade'); $table->string('model'); $table->string('color'); $table->integer('year'); $table->decimal('price', 15, 2); $table->string('image'); $table->timestamps(); }); |
📚 Penjelasan Kolom:
-
$table->id();
Primary key untuk tabelcars
. -
$table->foreignId('merk_id')->constrained('merks')->onDelete('cascade');
Membuat relasi ke tabelmerks
. Jadi satu mobil akan terhubung dengan satu merk.onDelete('cascade')
artinya: kalau sebuah merk dihapus, maka semua mobil dengan merk itu juga ikut terhapus. -
$table->string('model');
Nama model mobil, seperti “Civic”, “Avanza”, dll. -
$table->string('color');
Warna mobil. -
$table->integer('year');
Tahun produksi. -
$table->decimal('price', 15, 2);
Harga mobil dengan format desimal. Maksimal 15 digit dan 2 digit di belakang koma. -
$table->string('image');
Untuk menyimpan nama file gambar mobil (nanti bisa disimpan di folderstorage
). -
$table->timestamps();
Menambahkan kolomcreated_at
danupdated_at
.
Run the Migration Again In CMD:
✅ Langkah selanjutnya:
Setelah file create_merks_table.php
dan create_cars_table.php
sudah diedit, jalankan ulang migration dengan perintah:
1 |
php artisan migrate |
Penjelasan:
-
Perintah ini akan menjalankan migration baru yang belum pernah dijalankan tanpa menghapus tabel yang sudah ada.
-
Jika migration untuk tabel
merks
dancars
belum pernah dijalankan sebelumnya, maka tabel akan dibuat. -
Jika tabel sudah ada dan kamu hanya mengubah migration, Laravel tidak akan otomatis memperbarui tabel yang sudah ada.
Jadi kalau kamu ingin mengubah struktur tabel yang sudah ada, kamu perlu buat migration baru (migration alter) untuk perubahan terbaru
⚠️ Catatan Penting
-
Jangan langsung edit migration yang sudah pernah dijalankan dan berharap tabel ikut berubah otomatis, karena Laravel tidak menjalankan ulang migration yang sudah dijalankan.
-
Untuk perubahan struktur tabel setelah migration pertama, buat file migration baru dengan perintah:
1 |
php artisan make:migration update_cars_table --table=cars |
Kalau kamu baru mulai dan belum ada data penting, migrate:fresh
bisa jadi opsi cepat. Tapi kalau sudah ada data dan mau aman, cukup pakai php artisan migrate
atau buat migration baru untuk perubahan.
Lalu isi file migration tersebut dengan perubahan yang ingin kamu lakukan.
🔁 STEP 4 — Define Relationships in Models
Setelah kamu membuat model Merk
dan Car
, sekarang waktunya untuk mendefinisikan relasi antar tabel di dalam model, supaya data bisa saling terhubung.
📄 Edit app/Models/Merk.php
app/Models/Merk.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Merk extends Model { protected $fillable = ['name']; public function cars() { return $this->hasMany(Car::class); // Relasi: Satu merk bisa punya banyak mobil } } |
🔗 Penjelasan:
-
protected $fillable = ['name'];
Artinya hanya kolomname
yang bisa diisi secara massal (mass assignment), misalnya saat insert data. -
public function cars()
Fungsi ini mendefinisikan relasi one-to-many antaraMerk
danCar
. -
$this->hasMany(Car::class);
Menyatakan bahwa satu merk bisa memiliki banyak mobil.
app/Models/Car.php
1 2 3 4 5 6 7 8 9 10 11 12 13 |
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Car extends Model { protected $fillable = ['merk_id', 'model', 'color', 'year', 'price', 'image']; public function merk() { return $this->belongsTo(Merk::class); } } |
🔗 Penjelasan:
-
protected $fillable = [...]
Mendefinisikan field apa saja yang bisa diisi saat insert/update data.
Ini penting untuk menghindari MassAssignmentException di Laravel. -
public function merk()
Fungsi ini mendefinisikan relasi many-to-one, yaitu:Setiap mobil (
Car
) hanya memiliki satu merk (Merk
). -
$this->belongsTo(Merk::class);
Artinya fieldmerk_id
di tabelcars
adalah foreign key yang merujuk ke tabelmerks
.
📦 STEP 5 — Create Controller
1 |
php artisan make:controller CarController -r |
🛠️ Penjelasan:
-
php artisan make:controller
Adalah perintah Artisan (CLI-nya Laravel) untuk membuat controller. -
CarController
Nama controller yang akan kita buat. Di Laravel, biasanya nama controller memakai akhiranController
. -
-r
Singkatan dari--resource
, yaitu opsi untuk secara otomatis membuat semua method dasar CRUD seperti:-
index()
→ untuk menampilkan daftar data -
create()
→ menampilkan form tambah data -
store()
→ menyimpan data baru -
show()
→ menampilkan detail data tertentu -
edit()
→ menampilkan form edit -
update()
→ menyimpan perubahan data -
destroy()
→ menghapus data
-
app/Http/Controllers/CarController.php
🌐 STEP 6 — Routing
Edit routes/web.php
1 2 3 4 5 6 7 8 9 |
<?php use App\Http\Controllers\CarController; use Illuminate\Support\Facades\Route; Route::get('/', function () { return view('welcome'); }); Route::resource('/car', CarController::class); |
🔍 Penjelasan:
-
Route::get('/', ...)
Ini adalah route untuk halaman utama (localhost:8000/
) yang menampilkan viewwelcome
. -
Route::resource('/car', CarController::class);
Ini adalah route otomatis (resource route) yang secara default menghasilkan 7 route berikut:
HTTP Method | URI | Action | Route Name |
---|---|---|---|
GET | /car | index | car.index |
GET | /car/create | create | car.create |
POST | /car | store | car.store |
GET | /car/{car} | show | car.show |
GET | /car/{car}/edit | edit | car.edit |
PUT/PATCH | /car/{car} | update | car.update |
DELETE | /car/{car} | destroy | car.destroy |
Dengan satu baris Route::resource
, kamu sudah dapat akses CRUD lengkap! Tinggal buat view dan isi method di CarController
.
🖼️ STEP 7 — Create Views Folder
Agar aplikasi bisa menampilkan data ke pengguna, kita perlu membuat Blade View di Laravel. File view ini akan digunakan untuk menampilkan daftar mobil, form input, dan lain-lain.
✅ Struktur Blade View yang Akan Kita Buat:
✅ Struktur Blade View:
1 2 3 4 5 |
resources/views/ ├── layout/ │ └── app.blade.php ← Layout utama (include Bootstrap) ├── car/ │ └── index.blade.php ← Tampilkan list mobil |
php artisan make:view nama-folder.nama-file
Create the folder car dengan nama file layout:
1 |
php artisan make:view layout.app |
1. resources/views/layout/app.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<!DOCTYPE html> <html> <head> <title>Car Management</title> <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <div class="container mt-5"> <h2 class="mb-4">@yield('title')</h2> @yield('content') </div> </body> </html> |
Create the folder car dengan nama file index:
1 |
php artisan make:view car.index |
resources/views/car/index.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<h2>Car List</h2> <a href="{{ route('car.create') }}">Add Car</a> @if(session('message')) <p>{{ session('message') }}</p> @endif <table border="1" cellpadding="8"> <tr> <th>ID</th><th>Merk</th><th>Model</th><th>Color</th><th>Year</th><th>Price</th><th>Image</th><th>Actions</th> </tr> @foreach ($cars as $car) <tr> <td>{{ $car->id }}</td> <td>{{ $car->merk->name }}</td> <td>{{ $car->model }}</td> <td>{{ $car->color }}</td> <td>{{ $car->year }}</td> <td>{{ $car->price }}</td> <td><img src="{{ asset('storage/'.$car->image) }}" width="100" alt="Car Image"></td> <td> <a href="">View</a> | <a href="">Edit</a> <form action="" method="POST" style="display:inline;"> @csrf @method('DELETE') <button type="submit">Delete</button> </form> </td> </tr> @endforeach </table> |
🆕 CREATE — Form Tambah Data Mobil
resources/views/car/create.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
@extends('layout.app') @section('title', 'Add New Car') @section('content') <form action="{{ route('car.store') }}" method="POST" enctype="multipart/form-data"> @csrf <div class="mb-3"> <label>Merk</label> <select name="merk_id" class="form-control"> @foreach ($merks as $merk) <option value="{{ $merk->id }}">{{ $merk->name }}</option> @endforeach </select> </div> <div class="mb-3"> <label>Model</label> <input type="text" name="model" class="form-control"> </div> <div class="mb-3"> <label>Color</label> <input type="text" name="color" class="form-control"> </div> <div class="mb-3"> <label>Year</label> <input type="number" name="year" class="form-control"> </div> <div class="mb-3"> <label>Price</label> <input type="number" name="price" class="form-control"> </div> <div class="mb-3"> <label>Image</label> <input type="file" name="image" class="form-control"> </div> <button class="btn btn-primary" type="submit">Save</button> </form> @endsection |
CarController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
<?php namespace App\Http\Controllers; use App\Models\Car; use App\Models\Merk; use Illuminate\Http\Request; class CarController extends Controller { /** * Display a listing of the resource. */ public function index() { // $cars = Car::with('merk')->get(); return view('car.index', compact('cars')); } /** * Show the form for creating a new resource. */ public function create() { // $merks = Merk::all(); return view('car.create', compact('merks')); } /** * Store a newly created resource in storage. */ public function store(Request $request) { // $data = $request->validate([ 'merk_id' => 'required|exists:merks,id', 'model' => 'required', 'color' => 'required', 'year' => 'required|numeric', 'price' => 'required|numeric', 'image' => 'required|image|mimes:jpg,jpeg,png' ]); if ($request->hasFile('image')) { $data['image'] = $request->file('image')->store('car_images', 'public'); } Car::create($data); return redirect()->route('car.index')->with('message', 'Car added successfully!'); } /** * Display the specified resource. */ public function show(string $id) { // } /** * Show the form for editing the specified resource. */ public function edit(string $id) { // } /** * Update the specified resource in storage. */ public function update(Request $request, string $id) { // } /** * Remove the specified resource from storage. */ public function destroy(string $id) { // } } |
Jangan lupa nyalakan
1 |
php artisan storage:link |
Updatenya
Index.blade
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
@extends('layout.app') @section('title', 'Car List') @section('content') <a href="{{ route('car.create') }}" class="btn btn-primary mb-3">Add New Car</a> @if(session('message')) <div class="alert alert-success">{{ session('message') }}</div> @endif <table class="table table-bordered"> <thead class="table-dark"> <tr> <th>ID</th><th>Merk</th><th>Model</th><th>Color</th><th>Year</th><th>Price</th><th>Image</th><th>Actions</th> </tr> </thead> <tbody> @foreach ($cars as $car) <tr> <td>{{ $car->id }}</td> <td>{{ $car->merk->name }}</td> <td>{{ $car->model }}</td> <td>{{ $car->color }}</td> <td>{{ $car->year }}</td> <td>Rp {{ number_format($car->price, 0, ',', '.') }}</td> <td> <img src="{{ asset('storage/'.$car->image) }}" width="100" alt="Car Image"> </td> <td> <a href="" class="btn btn-info btn-sm">View</a> <a href="" class="btn btn-warning btn-sm">Edit</a> <form action="" method="POST" style="display:inline;"> @csrf @method('DELETE') <button type="submit" class="btn btn-danger btn-sm" onclick="return confirm('Are you sure?')">Delete</button> </form> </td> </tr> @endforeach </tbody> </table> @endsection |
Create.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
@extends('layout.app') @section('title', 'Add New Car') @section('content') <form action="{{ route('car.store') }}" method="POST" enctype="multipart/form-data"> @csrf <div class="mb-3"> <label>Merk</label> <select name="merk_id" class="form-control"> @foreach ($merks as $merk) <option value="{{ $merk->id }}">{{ $merk->name }}</option> @endforeach </select> </div> <div class="mb-3"> <label>Model</label> <input type="text" name="model" class="form-control"> </div> <div class="mb-3"> <label>Color</label> <input type="text" name="color" class="form-control"> </div> <div class="mb-3"> <label>Year</label> <input type="number" name="year" class="form-control"> </div> <div class="mb-3"> <label>Price</label> <input type="number" name="price" class="form-control"> </div> <div class="mb-3"> <label>Image</label> <input type="file" name="image" class="form-control"> </div> <button class="btn btn-primary" type="submit">Save</button> </form> @endsection |
Kita buatkan data dummy dulu
1 |
php artisan tinker |
1 2 3 4 5 6 7 8 9 |
\App\Models\Merk::create(['name' => 'Toyota']); \App\Models\Car::create([ 'merk_id' => 1, // ID dari merk Toyota 'model' => 'Avanza', 'color' => 'Silver', 'year' => 2020, 'price' => 180000, 'image' => 'car_images/avanza.jpg' // pastikan file ini ada di storage/app/public/car_images ]); |
🧪 Jalan kan servernya
1 |
php artisan serve |
Untuk menjalan kan serve kamu bisa php artisan serve di sini kamu
🧪 Access in Browser
1 2 |
http://localhost:8000/car |