Nah kamu udh selesai create kita coba lanjut
Oke, kamu sudah punya struktur CRUD Laravel 9/10 untuk data Car dengan relasi ke Merk yang cukup lengkap, tinggal kamu lengkapi fitur show
, edit
, update
, dan destroy
agar benar-benar lengkap. Di bawah ini saya lengkapi bagian CarController
dan juga tambahkan blade file edit
dan show
.
✅ CarController Tambahan:
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 |
// Show detail mobil public function show($id) { $car = Car::with('merk')->findOrFail($id); return view('car.show', compact('car')); } // Form edit mobil public function edit($id) { $car = Car::findOrFail($id); $merks = Merk::all(); return view('car.edit', compact('car', 'merks')); } // Proses update mobil public function update(Request $request, $id) { $car = Car::findOrFail($id); $data = $request->validate([ 'merk_id' => 'required|exists:merks,id', 'model' => 'required', 'color' => 'required', 'year' => 'required|numeric', 'price' => 'required|numeric', 'image' => 'nullable|image|mimes:jpg,jpeg,png' ]); if ($request->hasFile('image')) { $data['image'] = $request->file('image')->store('car_images', 'public'); } $car->update($data); return redirect()->route('car.index')->with('message', 'Car updated successfully!'); } // Hapus data mobil public function destroy($id) { $car = Car::findOrFail($id); $car->delete(); return redirect()->route('car.index')->with('message', 'Car deleted successfully!'); } |
📄 resources/views/car/edit.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 39 40 41 |
@extends('layout.app') @section('title', 'Edit Car') @section('content') <form action="{{ route('car.update', $car) }}" method="POST" enctype="multipart/form-data"> @csrf @method('PUT') <div class="mb-3"> <label>Merk</label> <select name="merk_id" class="form-control"> @foreach ($merks as $merk) <option value="{{ $merk->id }}" {{ $car->merk_id == $merk->id ? 'selected' : '' }}> {{ $merk->name }} </option> @endforeach </select> </div> <div class="mb-3"> <label>Model</label> <input type="text" name="model" class="form-control" value="{{ $car->model }}"> </div> <div class="mb-3"> <label>Color</label> <input type="text" name="color" class="form-control" value="{{ $car->color }}"> </div> <div class="mb-3"> <label>Year</label> <input type="number" name="year" class="form-control" value="{{ $car->year }}"> </div> <div class="mb-3"> <label>Price</label> <input type="number" name="price" class="form-control" value="{{ $car->price }}"> </div> <div class="mb-3"> <label>Image</label><br> <img src="{{ asset('storage/'.$car->image) }}" width="100" alt="Car Image"><br><br> <input type="file" name="image" class="form-control"> </div> <button class="btn btn-success" type="submit">Update</button> </form> @endsection |
📄 resources/views/car/show.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
@extends('layout.app') @section('title', 'Car Details') @section('content') <div class="card"> <div class="card-header"> Detail Mobil: {{ $car->model }} </div> <div class="card-body"> <p><strong>Merk:</strong> {{ $car->merk->name }}</p> <p><strong>Model:</strong> {{ $car->model }}</p> <p><strong>Color:</strong> {{ $car->color }}</p> <p><strong>Year:</strong> {{ $car->year }}</p> <p><strong>Price:</strong> Rp {{ number_format($car->price, 0, ',', '.') }}</p> <img src="{{ asset('storage/'.$car->image) }}" width="200" alt="Car Image"> </div> <div class="card-footer"> <a href="{{ route('car.index') }}" class="btn btn-secondary">Back</a> </div> </div> @endsection |
🔀 Tambahkan Routing CRUD Lengkap di routes/web.php
1 |
Route::resource('car', CarController::class); |
🔀 Perbaikin tampilannya menjadi terbaru di 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 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="{{ route('car.show', $car->id) }}" class="btn btn-info btn-sm">View</a> <a href="{{ route('car.edit', $car->id) }}" 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 |
✅ 1. Install Laravel Breeze untuk Auth (Login/Register)
Buka terminal dan jalankan:
1 2 3 4 |
composer require laravel/breeze --dev php artisan breeze:install npm install && npm run dev php artisan migrate |
Pilih yang livewire
Ini akan menambahkan:
- Halaman Login, Register, Forgot Password
- Route auth di
routes/auth.php
- Otomatis buat tabel
users
di database
✅ 2. Tambahkan Middleware auth
ke Route car
Edit routes/web.php
, ubah route car
seperti ini:
1 2 3 4 5 |
use App\Http\Controllers\CarController; Route::middleware(['auth'])->group(function () { Route::resource('car', CarController::class); }); |
Dengan begini, hanya user yang sudah login bisa akses /car
.
✅ 3. Buat Akun User Lewat Seeder
Buka file database/seeders/DatabaseSeeder.php
dan tambahkan:
1 2 3 4 5 6 7 8 9 10 11 |
use App\Models\User; use Illuminate\Support\Facades\Hash; public function run(): void { User::create([ 'name' => 'Admin User', 'password' => Hash::make('password123'), ]); } |
Lalu jalankan seeder:
1 |
php artisan db:seed |
✅ 4. Jalankan dan Tes Login
1 |
php artisan serve |
Lalu buka:
http://127.0.0.1:8000/login
Masukkan:
- Email:
[email protected]
- Password:
password123
Setelah login, kamu bisa akses /car
. Kalau belum login, otomatis akan diarahkan ke halaman login.
Berikut implementasi tombol logout langsung di halaman daftar mobil (car list
) menggunakan penjelasan dan struktur yang sesuai dengan standar Laravel (Breeze atau Laravel default), dan diletakkan dengan rapi di atas tabel, hanya ditampilkan jika user sudah login:
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 |
@extends('layout.app') @section('title', 'Car List') @section('content') {{-- Tombol Tambah dan Logout --}} <div style="margin-bottom: 15px;"> <a href="{{ route('car.create') }}" class="btn btn-primary">Add Car</a> @auth <form method="POST" action="{{ route('logout') }}" style="display:inline; float: right;"> @csrf <button type="submit" class="btn btn-danger"> Logout </button> </form> @endauth </div> {{-- Pesan Flash --}} @if(session('message')) <p>{{ session('message') }}</p> @endif @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="{{ route('car.show', $car->id) }}" class="btn btn-info btn-sm">View</a> <a href="{{ route('car.edit', $car->id) }}" class="btn btn-warning btn-sm">Edit</a> <form action="{{ route('car.destroy', $car->id) }}" 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 |
Update
..\resources\views\livewire\pages\auth\login.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 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 |
<?php use App\Livewire\Forms\LoginForm; use Illuminate\Support\Facades\Session; use Livewire\Attributes\Layout; use Livewire\Volt\Component; new #[Layout('layouts.guest')] class extends Component { public LoginForm $form; /** * Handle an incoming authentication request. */ public function login(): void { $this->validate(); $this->form->authenticate(); Session::regenerate(); $this->redirectIntended(default: route('car.index', absolute: false), navigate: true); } }; ?> <div> <!-- Session Status --> <x-auth-session-status class="mb-4" :status="session('status')" /> <form wire:submit="login"> <!-- Email Address --> <div> <x-input-label for="email" :value="__('Email')" /> <x-text-input wire:model="form.email" id="email" class="block mt-1 w-full" type="email" name="email" required autofocus autocomplete="username" /> <x-input-error :messages="$errors->get('form.email')" class="mt-2" /> </div> <!-- Password --> <div class="mt-4"> <x-input-label for="password" :value="__('Password')" /> <x-text-input wire:model="form.password" id="password" class="block mt-1 w-full" type="password" name="password" required autocomplete="current-password" /> <x-input-error :messages="$errors->get('form.password')" class="mt-2" /> </div> <!-- Remember Me --> <div class="block mt-4"> <label for="remember" class="inline-flex items-center"> <input wire:model="form.remember" id="remember" type="checkbox" class="rounded dark:bg-gray-900 border-gray-300 dark:border-gray-700 text-indigo-600 shadow-sm focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:focus:ring-offset-gray-800" name="remember"> <span class="ms-2 text-sm text-gray-600 dark:text-gray-400">{{ __('Remember me') }}</span> </label> </div> <div class="flex items-center justify-end mt-4"> @if (Route::has('password.request')) <a class="underline text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-offset-gray-800" href="{{ route('password.request') }}" wire:navigate> {{ __('Forgot your password?') }} </a> @endif <x-primary-button class="ms-3"> {{ __('Log in') }} </x-primary-button> </div> </form> </div> |
Sekarang Ubah web.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 |
<?php use Illuminate\Support\Facades\Route; use App\Http\Controllers\CarController; use Illuminate\Support\Facades\Auth; Route::view('/', 'welcome'); Route::view('dashboard', 'dashboard') ->middleware(['auth', 'verified']) ->name('dashboard'); Route::view('profile', 'profile') ->middleware(['auth']) ->name('profile'); Route::post('/logout', function () { request()->session()->invalidate(); request()->session()->regenerateToken(); Auth::logout(); return redirect('/'); })->middleware('auth')->name('logout'); // Route yang membutuhkan autentikasi Route::middleware(['auth'])->group(function () { Route::resource('car', CarController::class); }); require __DIR__.'/auth.php'; |
✅ Penjelasan Singkat:
- Logout hanya muncul saat user login, pakai
@auth
. - Logout pakai
POST
method, jadi perlu<form>
+@csrf
. - Tidak muncul di setiap baris, tapi di bagian atas halaman, lebih bersih dan konsisten.