Inventaris Lab Laravel 12 : Bagian #08 - MEMBUAT HALAMAN CRUD ITEM — Minarsih TECH Install Web App

Inventaris Lab Laravel 12 : Bagian #08 - MEMBUAT HALAMAN CRUD ITEM

profil-penulis

Belajar Bareng Minarsih - Edisi Ngoding

10 Oktober 2025

Tujuan: Di bagian ini, kita akan membangun fitur CRUD yang lebih kompleks, yaitu untuk mengelola data barang/item. Kita akan menerapkan kembali teknik refactoring dan juga belajar cara menampilkan data yang berhubungan antar tabel (misalnya, menampilkan nama kategori pada setiap item).

 

Langkah 1: Menyiapkan Route & Controller

Seperti biasa, kita siapkan "jalan" dan "otak" terlebih dahulu.

  1. Memastikan Controller Sudah Ada:
    • File ItemController.php sudah dibuatkan untuk kita oleh perintah php artisan make:model Item -msr pada bagian KONFIGURASI DATABASE & FONDASI PROYEK.


       
  2. Mendaftarkan Resource Route:
    • Buka file routes/web.php.


       
    • Impor ItemController di bagian atas file:
       
      use App\Http\Controllers\ItemController;

       
    • Di dalam grup Route::middleware('auth')->group(...), tambahkan satu baris route resource untuk item.
       
      Route::middleware('auth')->group(function () {
          // ... route dashboard, users, category
      
          Route::resource('item', ItemController::class);
      
      });


       

  1. Melihat Daftar Route:
    • Untuk memastikan rute-rute CRUD Item sudah terbuat, jalankan perintah ini di terminal:
       
      php artisan route:list --name=item

 

Langkah 2: Mengisi Logika ItemController (Bagian Index)

Sekarang, kita isi logika pada controller untuk mengambil data semua item dari database.

  1. Buka file app/Http/Controllers/ItemController.php.


     
  2. Pastikan import model Item sudah ada di ItemController. Biasanya baris ini akan otomatis dibuat karena model Item sebelumnya dibuat dengan perintah-msr:
     
    use App\Models\Item;

     
  3. Tambahkan variabel protected dengan menyalinnya dari CategoryController dan menyesuaikan isinya:
     
    class ItemController extends Controller
    {
    
        // Variabel untuk data umum
    
        protected $title = 'Item';
    
        protected $menu = 'item';
    
        protected $directory = 'admin.item'; // Diubah ke folder view item

  4. Isi fungsi index() untuk mengambil data dan mengirimkannya ke view:
     
    public function index()
    {
        // Menyiapkan array untuk dikirim ke view
        $data['title'] = $this->title;
        $data['menu'] = $this->menu;
    
        // Mengambil data dari database
        $data['items'] = Item::with('category')->latest()->get();
    
        // Me-return view beserta data
        return view($this->directory . '.index', $data);
    }
    Pe
    

     
  5. Penjelasan Kode: Perhatikan ada tambahan .with('category'). Ini adalah teknik Eager Loading di Laravel. Perintah ini berarti: "Ambil semua data item, dan untuk setiap item, sertakan juga data dari relasi category-nya". Ini jauh lebih efisien daripada mengambil data kategori satu per satu di dalam looping.

 

Langkah 3: Menyiapkan File-File View (Cara Cepat)

Kita akan kembali menggunakan metode duplikasi untuk mempercepat pekerjaan.

  1. Di panel file VS Code, buka direktori resources/views/admin/.
  2. Klik kanan pada folder category, lalu pilih Copy.


     
  3. Klik kanan lagi pada folder admin, lalu pilih Paste.


     
  4. Rename folder category copy menjadi item.


     
  5. Sekarang kita memiliki folder item yang berisi file index, create, dan edit yang siap untuk kita modifikasi.

 

Langkah 4: Menyesuaikan Halaman Index Item

Sekarang kita akan mengubah file index.blade.php di dalam folder item agar sesuai untuk menampilkan data barang.

  1. Buka file resources/views/admin/item/index.blade.php.
  2. KODE SEBELUM PENYESUAIAN (Masih Kode Milik Category):
     
    @extends('admin.layouts.app')
    
    @section('css')
    
        {{-- CSS Tambahan --}}
    
    @endsection
    
    
    
    @section('content')
    
        <div class="card">
    
            <div class="card-body">
    
                <h5 class="card-title fw-semibold mb-4">Data {{ $title }}</h5>
    
                <a href="{{ route('category.create') }}" class="btn btn-primary mb-4">Tambah Data {{ $title }}</a>
    
    
    
                <div class="table-responsive">
    
                    <table id="datatable" class="table table-striped">
    
                        <thead>
    
                            <th>No</th>
    
                            <th>Nama</th>
    
                            <th>Aksi</th>
    
                            </tr>
    
                        </thead>
    
                        <tbody>
    
                            @foreach ($categories as $item)
    
                                <tr>
    
                                    <td>{{ $loop->iteration }}</td>
    
                                    <td>{{ $item->name }}</td>
    
                                    <td>
    
                                        <a href="{{ route('category.edit', $item->id) }}" class="btn btn-warning btn-sm">Ubah</a>
    
                                        <form id="deleteForm{{ $item->id }}"
    
                                            action="{{ route('category.destroy', $item->id) }}" method="POST" class="d-inline">
    
                                            @csrf
    
                                            @method('DELETE')
    
                                            <button type="button" class="btn btn-danger btn-sm"
    
                                                onclick="confirmDelete({{ $item->id }})">Hapus</button>
    
                                        </form>
    
                                    </td>
    
                                </tr>
    
                            @endforeach 
    
                        </tbody>
    
                    </table>
    
                </div>
    
            </div>
    
        </div>
    
    @endsection
    
    
    
    @section('js')
    
        <script>
    
            $(document).ready(function() {
    
                $('#datatable').DataTable();
    
            });
    
    
    
            // Script untuk SweetAlert
    
            function confirmDelete(id) {
    
                swal({
    
                        title: "Apakah anda yakin?",
    
                        text: "Data yang dihapus tidak dapat dikembalikan!",
    
                        icon: "warning",
    
                        buttons: true,
    
                        dangerMode: true,
    
                    })
    
                    .then((willDelete) => {
    
                        if (willDelete) {
    
                            // Jika pengguna menekan "OK", submit form
    
                            $('#deleteForm' + id).submit();
    
                        } else {
    
                            // Jika pengguna menekan "Cancel"
    
                            swal("Data tidak jadi dihapus!", {
    
                                icon: "error",
    
                            });
    
                        }
    
                    });
    
            }
    
        </script>
    
    @endsection




     

  3. Lakukan Penyesuaian dengan Teliti:
    • Tombol Tambah & Rute: Ubah semua rute dari category.* menjadi item.*.


       
    • Looping Data: Ubah @foreach ($categories as $item) menjadi @foreach ($items as $item).


       
    • Header Tabel: Sesuaikan <thead> dengan kolom-kolom dari tabel items: No, Nama, Foto,  Kategori, Kode Unik, Kondisi, dan Aksi.


       
    • Isi Tabel: Sesuaikan <tbody> untuk menampilkan data-data tersebut. Untuk menampilkan nama kategori, kita akan memanggilnya melalui relasi: {{ $item->category->name }}.


       
    • Tempat Foto: Tentukan folder di dalam public yang akan digunakan untuk menyimpan foto atau gambar. Pada contoh ini, file akan disimpan di folder public/photos. Untuk menampilkan foto yang tersimpan di folder tersebut, gunakan link href="{{ asset('photos/' . $item->photo) }}". Tambahkan atribut target="_blank" agar saat link diklik, foto terbuka di tab baru.


       
  4. KODE SETELAH PENYESUAIAN (Kode Final untuk item/index.blade.php):
    Ganti seluruh isi file dengan kode yang sudah disesuaikan ini:
     
    @extends('admin.layouts.app')
    @section('css')
    
        {{-- CSS Tambahan --}}
    
    @endsection
    
    
    
    @section('content')
    
        <div class="card">
    
            <div class="card-body">
    
                <h5 class="card-title fw-semibold mb-4">Data {{ $title }}</h5>
    
                <a href="{{ route('item.create') }}" class="btn btn-primary mb-4">Tambah Data {{ $title }}</a>
    
    
    
                <div class="table-responsive">
    
                    <table id="datatable" class="table table-striped">
    
                        <thead>
    
                            <tr>
    
                                <th>No</th>
    
                                <th>Nama</th>
    
                                <th>Foto</th>
    
                                <th>Kategori</th>
    
                                <th>Kode Unik</th>
    
                                <th>Kondisi</th>
    
                                <th>Aksi</th>
    
                            </tr>
    
                        </thead>
    
                        <tbody>
    
                            @foreach ($items as $item)
    
                                <tr>
    
                                    <td>{{ $loop->iteration }}</td>
    
                                    <td>{{ $item->name }}</td>
    
                                    <td><a href="{{ asset('photos/' . $item->photo) }}" target="_blank">Lihat Foto</a>
          </td>
    
                                    <td>{{ $item->category->name }}</td>
    
                                    <td>{{ $item->unique_code }}</td>
    
                                    <td>{{ $item->condition }}</td>
    
                                    <td>
    
                                        <a href="{{ route('item.edit', $item->id) }}" class="btn btn-warning btn-sm">Ubah</a>
    
                                        <form id="deleteForm{{ $item->id }}"
    
                                            action="{{ route('item.destroy', $item->id) }}" method="POST" class="d-inline">
    
                                            @csrf
    
                                            @method('DELETE')
    
                                            <button type="button" class="btn btn-danger btn-sm"
    
                                                onclick="confirmDelete({{ $item->id }})">Hapus</button>
    
                                        </form>
    
                                    </td>
    
                                </tr>
    
                            @endforeach
    
                        </tbody>
    
                    </table>
    
                </div>
    
            </div>
    
        </div>
    
    @endsection
    
    
    
    @section('js')
    
        <script>
    
            $(document).ready(function() {
    
                $('#datatable').DataTable();
    
            });
    
    
    
            // Script untuk SweetAlert
    
            function confirmDelete(id) {
    
                swal({
    
                        title: "Apakah anda yakin?",
    
                        text: "Data yang dihapus tidak dapat dikembalikan!",
    
                        icon: "warning",
    
                        buttons: true,
    
                        dangerMode: true,
    
                    })
    
                    .then((willDelete) => {
    
                        if (willDelete) {
    
                            // Jika pengguna menekan "OK", submit form
    
                            $('#deleteForm' + id).submit();
    
                        } else {
    
                            // Jika pengguna menekan "Cancel"
    
                            swal("Data tidak jadi dihapus!", {
    
                                icon: "error",
    
                            });
    
                        }
    
                    });
    
            }
    
        </script>
    
    @endsection



 

Langkah 5: Menambahkan Menu Item di Sidebar

Agar halaman daftar item yang baru kita buat bisa diakses, kita perlu menambahkan link menunya di sidebar.

  1. Buka file resources/views/admin/layouts/sidebar.blade.php.


     
  2. Gunakan shortcut keyboard Alt + Shift + Arrow Down untuk menduplikasi blok kode menu "Data Category".


     
  3. Sesuaikan kode hasil duplikasi tersebut untuk "Data Item".
    • Ubah Request::is('category*') menjadi Request::is('item*').


       
    • Ubah route('category.index') menjadi route('item.index').


       
    • Ganti ikon ti ti-category menjadi ti ti-box agar sesuai.


       
    • Ganti teks menu Data Category menjadi Data Item.


       
  4. KODE SETELAH PENYESUAIAN (Final Sidebar): Blok "Datamaster" Anda sekarang akan terlihat lengkap seperti ini.
     
    {{-- MENU DATAMASTER --}}
    <li class="nav-small-cap">
    
        <i class="ti ti-dots nav-small-cap-icon fs-4"></i>
    
        <span class="hide-menu">Datamaster</span>
    
    </li>
    
    {{-- Menu Users --}}
    
    <li class="sidebar-item {{ Request::is('users*') ? 'selected' : '' }}">
    
        <a class="sidebar-link {{ Request::is('users*') ? 'active' : '' }}"
    
            href="{{ route('users.index') }}" aria-expanded="false">
    
            <span><i class="ti ti-users"></i></span>
    
            <span class="hide-menu">Data Users</span>
    
        </a>
    
    </li>
    
    {{-- Menu Category --}}
    
    <li class="sidebar-item {{ Request::is('category*') ? 'selected' : '' }}">
    
        <a class="sidebar-link {{ Request::is('category*') ? 'active' : '' }}"
    
            href="{{ route('category.index') }}" aria-expanded="false">
    
            <span><i class="ti ti-category"></i></span>
    
            <span class="hide-menu">Data Category</span>
    
        </a>
    
    </li>
    
    {{-- Menu Item --}}
    
    <li class="sidebar-item {{ Request::is('item*') ? 'selected' : '' }}">
    
        <a class="sidebar-link {{ Request::is('item*') ? 'active' : '' }}"
    
            href="{{ route('item.index') }}" aria-expanded="false">
    
            <span><i class="ti ti-box"></i></span>
    
            <span class="hide-menu">Data Item</span>
    
        </a>
    
    </li>
    

  1. Uji Coba Halaman Index Item:
    • Simpan file sidebar.blade.php.
    • Refresh browser Anda. Menu "Data Item" akan muncul di bawah "Data Category".


       
    • Klik menu "Data Item" tersebut.
    • Hasil: Halaman daftar item akan tampil dengan benar. Saat ini tabelnya masih kosong karena kita belum punya data item.


       

Langkah 6: Membuat Form Tambah Item

Membuat form untuk item akan sedikit lebih kompleks karena melibatkan lebih banyak jenis input, termasuk dropdown untuk memilih kategori dan input untuk mengunggah foto.

  1. Siapkan Logika di Controller (Fungsi create):
    • Buka app/Http/Controllers/ItemController.php.


       
    • Kita perlu mengambil semua data kategori dari database untuk ditampilkan di form. Impor Model Category di bagian atas:
       
      use App\Models\Category;

       
    • Isi fungsi create() dengan kode berikut:
      public function create()
      {
      
          $data['title'] = $this->title;
      
          $data['menu'] = $this->menu;
      
          // Ambil semua data kategori untuk dikirim ke view
      
          $data['categories'] = Category::all();
      
      
      
          return view($this->directory . '.create', $data);
      
      }

       
  2. Sesuaikan Tampilan Form (create.blade.php):
    • Buka file resources/views/admin/item/create.blade.php. Saat ini isinya masih berupa salinan dari form kategori.


       
    • Kita akan melakukan modifikasi besar. Ubah form agar memiliki input untuk Nama, Kategori, Foto, Kode Unik, dan Kondisi.




       
    • PENTING: Karena kita akan mengunggah file, tambahkan enctype="multipart/form-data" pada tag <form>.


       
    • Jangan lupa, ubah juga route ‘category.index’ menjadi ‘item.index’ di tombol Kembali.


       
  3. KODE SETELAH PENYESUAIAN (Kode Final create.blade.php): Ganti seluruh isi file dengan kode di bawah ini.
     
    @extends('admin.layouts.app')
    
    @section('css')
        {{-- CSS Tambahan --}}
    
    @endsection
    
    
    @section('content')
    
        <div class="card">
    
            <div class="card-body">
    
                <h5 class="card-title fw-semibold mb-4">Tambah Data {{ $title }}</h5>
    
                <div class="card">
    
                    <div class="card-body">
    
                        <form action="{{ route('item.store') }}" method="POST" enctype="multipart/form-data">
    
                            @csrf
    
                            {{-- Nama Item --}}
    
                            <div class="mb-3">
    
                                <label for="name" class="form-label">Nama Item</label>
    
                                <input type="text" class="form-control @error('name') is-invalid @enderror" name="name"
    
                                    id="name" placeholder="Nama Item" value="{{ old('name') }}">
    
                                @error('name')
    
                                    <small class="text-danger">{{ $message }}</small>
    
                                @enderror
    
                            </div>
    
    
    
                            {{-- Kategori --}}
    
                            <div class="mb-3">
    
                                <label for="category_id" class="form-label">Kategori</label>
    
                                <select class="form-select @error('category_id') is-invalid @enderror" name="category_id" id="category_id">
    
                                    <option value="" disabled selected>Pilih Kategori</option>
    
                                    @foreach ($categories as $category)
    
                                        <option value="{{ $category->id }}" {{ old('category_id') == $category->id ? 'selected' : '' }}>{{ $category->name }}</option>
    
                                    @endforeach
    
                                </select>
    
                                @error('category_id')
    
                                    <small class="text-danger">{{ $message }}</small>
    
                                @enderror
    
                            </div>
    
    
    
                            {{-- Foto --}}
    
                            <div class="mb-3">
    
                                <label for="photo" class="form-label">Foto</label>
    
                                <input type="file" class="form-control @error('photo') is-invalid @enderror" name="photo" id="photo">
    
                                @error('photo')
    
                                    <small class="text-danger">{{ $message }}</small>
    
                                @enderror
    
                            </div>
    
    
    
                             {{-- Kode Unik --}}
    
                             <div class="mb-3">
    
                                <label for="unique_code" class="form-label">Kode Unik</label>
    
                                <input type="text" class="form-control @error('unique_code') is-invalid @enderror" name="unique_code"
    
                                    id="unique_code" placeholder="Contoh: MM-001" value="{{ old('unique_code') }}">
    
                                @error('unique_code')
    
                                    <small class="text-danger">{{ $message }}</small>
    
                                @enderror
    
                            </div>
    
    
    
                            {{-- Kondisi --}}
    
                            <div class="mb-3">
    
                                <label for="condition" class="form-label">Kondisi</label>
    
                                <select class="form-select @error('condition') is-invalid @enderror" name="condition" id="condition">
    
                                    <option value="Baik" {{ old('condition') == 'Baik' ? 'selected' : '' }}>Baik</option>
    
                                    <option value="Rusak" {{ old('condition') == 'Rusak' ? 'selected' : '' }}>Rusak</option>
    
                                </select>
    
                                @error('condition')
    
                                    <small class="text-danger">{{ $message }}</small>
    
                                @enderror
    
                            </div>
    
    
    
                            {{-- Tombol --}}
    
                            <button type="submit" class="btn btn-primary">Simpan</button>
    
                            <a href="{{ route('item.index') }}" class="btn btn-warning">Kembali</a>
    
                        </form>
    
                    </div>
    
                </div>
    
            </div>
    
        </div>
    
    @endsection
    
    @section('js')
    
        {{-- JS Tambahan --}}
    
    @endsection

     

Penjelasan Baru:

  • @foreach ($categories as $category): Kita melakukan looping pada data $categories yang dikirim dari controller untuk membuat pilihan dropdown secara dinamis.

enctype="multipart/form-data": Atribut ini wajib ada pada form jika di dalamnya terdapat input untuk unggah file.

 

Langkah 7: Menyiapkan Logika Penyimpanan Data Item

Logika penyimpanan item akan lebih kompleks karena kita perlu menangani unggahan file foto.

  1. Siapkan Model Item.php:
    • Buka file app/Models/Item.php.


       
    • Tambahkan semua kolom baru ke dalam properti $fillable.


       
    • Kita juga akan mendefinisikan relasi ke Model Category di sini.
       
      <?php
      
      
      namespace App\Models;
      
      
      use Illuminate\Database\Eloquent\Model;
      
      
      
      class Item extends Model
      
      {
      
          protected $fillable = [
      
              'category_id',
      
              'name',
      
              'photo',
      
              'unique_code',
      
              'condition',
      
          ];
      
      
      
          // Mendefinisikan relasi "belongsTo" ke model Category
      
          public function category()
      
          {
      
              return $this->belongsTo(Category::class);
      
          }
      
      }
       
  2. Isi Logika store() di Controller:
    • Buka ItemController.php.


       
    • Isi fungsi store() dengan logika validasi, pemrosesan file, dan penyimpanan data.
       
      public function store(Request $request)
      
      {
      
          // 1. Validasi data
      
          $validatedData = $request->validate([
      
              'name' => 'required|max:255',
      
              'category_id' => 'required',
      
              'photo' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048',
      
              'unique_code' => 'nullable|unique:items',
      
              'condition' => 'required',
      
          ]);
      
      
      
          // 2. Proses upload foto jika ada
      
          if ($request->hasFile('photo')) {
      
              $image = $request->file('photo');
      
              // Buat nama file unik berdasarkan waktu
      
              $imageName = time() . '.' . $image->getClientOriginalExtension();
      
              // Pindahkan file ke folder public/photos
      
              $image->move(public_path('photos'), $imageName);
      
              // Simpan nama file ke dalam data yang akan divalidasi
      
              $validatedData['photo'] = $imageName;
      
          }
      
      
      
          // 3. Simpan data ke database
      
          $item = Item::create($validatedData);
      
      
      
          // 4. Redirect dengan pesan sukses
      
          if ($item) {
      
              return redirect()->route('item.index')->with([
      
                  'status' => 'success',
      
                  'title' => 'Berhasil',
      
                  'message' => 'Data Berhasil Ditambahkan!'
      
              ]);
      
          } else {
      
              return redirect()->route('item.index')->with([
      
                  'status' => 'danger',
      
                  'title' => 'Gagal',
      
                  'message' => 'Data Gagal Ditambahkan!'
      
              ]);
      
          }
      
      }

 

Langkah 8: Uji Coba Form Tambah Data

  1. Buka browser Anda, pergi ke halaman "Data Category", lalu klik tombol "Tambah Data Category".
  2. Anda akan melihat form tambah kategori yang baru saja kita buat.


     
  3. Coba isi nama kategori baru (misalnya "Laptop"), lalu klik Simpan.


     
  4. Hasil: Anda akan diarahkan kembali ke halaman daftar kategori, sebuah notifikasi SweetAlert "Berhasil Ditambahkan!" akan muncul, dan data "Laptop" akan tampil di dalam tabel.




 

Langkah 9: Membuat Form Ubah Item

Prosesnya akan sangat mirip dengan membuat form tambah, kita akan mengadaptasi kode yang sudah ada.

  1. Siapkan Logika di Controller (Fungsi edit):
    • Buka app/Http/Controllers/ItemController.php.
    • Cari fungsi edit(Item $item) yang masih kosong. Kita perlu mengambil data item yang akan diubah mengunakan Model Binding, sekaligus semua data kategori untuk pilihan dropdown.


       
    • Isi fungsi edit() dengan kode berikut:
       
      public function edit(Item $item)
      {
      
          // Menyiapkan data umum
      
          $data['title'] = $this->title;
      
          $data['menu'] = $this->menu;
      
          // Mencari data item berdasarkan ID menggunakan Model Binding
      
          $data['item'] = $item;
      
          // Ambil semua data kategori untuk dikirim ke view
      
          $data['categories'] = Category::all();
      
      
      
          // Me-return view beserta data
      
          return view($this->directory . '.edit', $data);
      
      }

       
  2. Sesuaikan Tampilan Form (edit.blade.php):
    • Buka file resources/views/admin/item/edit.blade.php.


       
    • Hapus semua isinya, lalu salin semua kode dari create.blade.php (dari folder item) dan tempel ke edit.blade.php ini.


       
    • Sekarang, kita perlu melakukan beberapa penyesuaian:
      • Ubah Judul Card: Ganti teks "Tambah Data" menjadi "Ubah Data".


         
      • Ubah Form Action & Method: Arahkan form ke route item.update dan tambahkan directive @method('PUT').


         
      • Ubah Nilai Input: Tambahkan data lama ($item->...) sebagai nilai default pada setiap input.


         
      • Tampilkan Foto Lama: Untuk input file, kita tidak bisa memberikan nilai default. Sebagai gantinya, kita akan tampilkan foto yang ada saat ini di atas input file.


         
  3. KODE SETELAH PENYESUAIAN (Kode Final edit.blade.php):
     
    @extends('admin.layouts.app')
    
    @section('css')
        {{-- CSS Tambahan --}}
    
    @endsection
    
    @section('content')
    
        <div class="card">
    
            <div class="card-body">
    
                <h5 class="card-title fw-semibold mb-4">Ubah Data {{ $title }}</h5>
    
                <div class="card">
    
                    <div class="card-body">
    
                        <form action="{{ route('item.update', $item->id) }}" method="POST" enctype="multipart/form-data">
    
                            @csrf
    
                            @method('PUT')
    
                            {{-- Nama Item --}}
    
                            <div class="mb-3">
    
                                <label for="name" class="form-label">Nama Item</label>
    
                                <input type="text" class="form-control @error('name') is-invalid @enderror" name="name"
    
                                    id="name" placeholder="Nama Item" value="{{ old('name', $item->name) }}">
    
                                @error('name')
    
                                    <small class="text-danger">{{ $message }}</small>
    
                                @enderror
    
                            </div>
    
    
    
                            {{-- Kategori --}}
    
                            <div class="mb-3">
    
                                <label for="category_id" class="form-label">Kategori</label>
    
                                <select class="form-select @error('category_id') is-invalid @enderror" name="category_id" id="category_id">
    
                                    <option value="" disabled>Pilih Kategori</option>
    
                                    @foreach ($categories as $category)
    
                                        <option value="{{ $category->id }}" {{ old('category_id', $item->category_id) == $category->id ? 'selected' : '' }}>{{ $category->name }}</option>
    
                                    @endforeach
    
                                </select>
    
                                @error('category_id')
    
                                    <small class="text-danger">{{ $message }}</small>
    
                                @enderror
    
                            </div>
    
    
    
                            {{-- Foto --}}
    
                            <div class="mb-3">
    
                                <label for="photo" class="form-label">Ganti Foto (Opsional)</label>
    
                                @if ($item->photo)
    
                                    <p>Foto saat ini: <img src="{{ asset('photos/' . $item->photo) }}" alt="Foto Item" width="100"></p>
    
                                @endif
    
                                <input type="file" class="form-control @error('photo') is-invalid @enderror" name="photo" id="photo">
    
                                @error('photo')
    
                                    <small class="text-danger">{{ $message }}</small>
    
                                @enderror
    
                            </div>
    
    
    
                             {{-- Kode Unik --}}
    
                             <div class="mb-3">
    
                                <label for="unique_code" class="form-label">Kode Unik</label>
    
                                <input type="text" class="form-control @error('unique_code') is-invalid @enderror" name="unique_code"
    
                                    id="unique_code" placeholder="Contoh: MM-001" value="{{ old('unique_code', $item->unique_code) }}">
    
                                @error('unique_code')
    
                                    <small class="text-danger">{{ $message }}</small>
    
                                @enderror
    
                            </div>
    
    
    
                            {{-- Kondisi --}}
    
                            <div class="mb-3">
    
                                <label for="condition" class="form-label">Kondisi</label>
    
                                <select class="form-select @error('condition') is-invalid @enderror" name="condition" id="condition">
    
                                    <option value="Baik" {{ old('condition', $item->condition) == 'Baik' ? 'selected' : '' }}>Baik</option>
    
                                    <option value="Rusak" {{ old('condition', $item->condition) == 'Rusak' ? 'selected' : '' }}>Rusak</option>
    
                                </select>
    
                                @error('condition')
    
                                    <small class="text-danger">{{ $message }}</small>
    
                                @enderror
    
                            </div>
    
    
    
                            {{-- Tombol --}}
    
                            <button type="submit" class="btn btn-primary">Simpan</button>
    
                            <a href="{{ route('item.index') }}" class="btn btn-warning">Kembali</a>
    
                        </form>
    
                    </div>
    
                </div>
    
            </div>
    
        </div>
    
    @endsection
    
    @section('js')
    
        {{-- JS Tambahan --}}
    
    @endsection





 

Langkah 10: Menyiapkan Logika Update Data Item

Logika update akan sedikit berbeda karena kita perlu memeriksa apakah ada file foto baru yang diunggah. Jika ada, kita hapus foto lama dan unggah yang baru.

  1. Buka ItemController.php.


     
  2. Impor facade File di bagian atas untuk membantu kita menghapus file lama.
     
    use Illuminate\Support\Facades\File;
    


     

  3. Isi fungsi update() dengan logika validasi, pemrosesan file opsional, dan pembaruan data.
     
    public function update(Request $request, Item $item)
    {
    
         // 1. Gunakan Route Model Binding, variabel $item sudah siap pakai.
    
        $validatedData = $request->validate([
    
            'name' => 'required|max:255',
    
            'category_id' => 'required',
    
            'photo' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048',
    
            'unique_code' => 'nullable|unique:items,unique_code,' . $item->id,
    
            'condition' => 'required',
    
        ]);
    
    
    
        // 2. Siapkan data dari hasil validasi.
    
        $updateData = $validatedData;
    
    
    
        // 3. Proses foto baru jika diupload: hapus yang lama, simpan yang baru.
    
        if ($request->hasFile('photo')) {
    
            // Hapus foto lama jika ada.
    
            if ($item->photo && File::exists(public_path('photos/' . $item->photo))) {
    
                File::delete(public_path('photos/' . $item->photo));
    
            }
    
    
    
            // Simpan foto baru dan tambahkan namanya ke data update.
    
            $image = $request->file('photo');
    
            $imageName = time() . '.' . $image->getClientOriginalExtension();
    
            $image->move(public_path('photos'), $imageName);
    
            $updateData['photo'] = $imageName;
    
        }
    
    
    
        // 4. Update data item di database.
    
        $updateProcess = $item->update($updateData);
    
    
    
        // 5. Redirect dengan pesan status berdasarkan hasil update.
    
        if ($updateProcess) {
    
            return redirect()->route('item.index')->with([
    
                'status' => 'success',
    
                'title' => 'Berhasil',
    
                'message' => 'Data Berhasil Diubah!'
    
            ]);
    
        } else {
    
            return redirect()->route('item.index')->with([
    
                'status' => 'danger',
    
                'title' => 'Gagal',
    
                'message' => 'Data Gagal Diubah!'
    
            ]);
    
        }
    
    }

 

Langkah 11: Uji Coba Form Ubah Data Item

  1. Buka browser Anda, pergi ke halaman "Data Item", lalu klik tombol "Ubah" pada salah satu data.
  2. Anda akan diarahkan ke form ubah, dan semua data item lama akan otomatis terisi.


     
  3. Lakukan dua skenario pengujian:
    • Skenario 1: Ubah data teks (misalnya nama atau kondisi) tanpa mengunggah foto baru. Klik "Simpan".


       
    • Skenario 2: Ubah data teks dan unggah foto baru. Klik "Simpan".


       
  4. Hasil: Di kedua skenario, Anda akan kembali ke halaman daftar item dengan notifikasi sukses, dan data di tabel akan diperbarui. Pada skenario 2, foto lama akan terhapus dari server dan digantikan oleh foto baru.





 

Langkah 12: Membuat Fitur Hapus Item

Ini adalah langkah terakhir untuk melengkapi CRUD Item. Logikanya akan sedikit berbeda karena kita juga harus menghapus file foto yang tersimpan di server.

  1. Siapkan Logika destroy() di Controller:
    • Buka app/Http/Controllers/ItemController.php.


       
    • Cari fungsi destroy(Item $item) yang masih kosong. Kita akan mengisinya dengan logika untuk mencari data, menghapus file fotonya, lalu menghapus data dari database.


       
    • Isi fungsi destroy() dengan kode berikut:
       
      public function destroy(Item $item)
      {
      
          // 1. Hapus file foto dari folder public jika ada.
      
          if ($item->photo && File::exists(public_path('photos/' . $item->photo))) {
      
              File::delete(public_path('photos/' . $item->photo));
      
          }
      
      
      
          // 2. Hapus data item dari database.
      
          $deleteProcess = $item->delete();
      
      
      
          // 3. Redirect dengan pesan status berdasarkan hasil proses hapus.
      
          if ($deleteProcess) {
      
              return redirect()->route('item.index')->with([
      
                  'status' => 'success',
      
                  'title' => 'Berhasil',
      
                  'message' => 'Data Berhasil Dihapus!'
      
              ]);
      
          } else {
      
              return redirect()->route('item.index')->with([
      
                  'status' => 'danger',
      
                  'title' => 'Gagal',
      
                  'message' => 'Data Gagal Dihapus!'
      
              ]);
      
          }
      
      }

 Penjelasan Kode:

  • File::exists(...): Perintah ini memeriksa apakah sebuah file benar-benar ada di dalam folder public/photos/.
  • File::delete(...): Jika file fotonya ada, perintah ini akan menghapusnya secara fisik dari server. Ini adalah langkah penting untuk menjaga agar server kita tidak penuh dengan file sampah.
  • $item->delete(): Perintah ini menghapus data item dari tabel items di database.

 

Langkah 13: Uji Coba Terakhir Fitur Hapus Item

Saatnya memastikan semua bagian (Tombol -> SweetAlert -> Controller -> Hapus File -> Hapus Data -> Redirect) bekerja dengan sempurna.

  1. Buka browser Anda dan pergi ke halaman "Data Item".
  2. Pastikan Anda memiliki data item yang memiliki foto. Jika belum, tambahkan satu.


     
  3. Klik tombol "Hapus" berwarna merah pada data item tersebut.
  4. Sebuah dialog konfirmasi dari SweetAlert akan muncul. Klik tombol "OK".


     
  5. Hasil: Anda akan diarahkan kembali ke halaman daftar item, notifikasi SweetAlert "Berhasil Dihapus!" akan muncul, dan baris data item tersebut akan hilang dari tabel. Anda juga bisa memeriksa folder public/photos di proyek Anda untuk memastikan file fotonya juga sudah terhapus.




     

Selamat! Anda telah berhasil membangun fungsionalitas CRUD yang lebih kompleks untuk halaman Item, termasuk menangani unggahan dan penghapusan file. Ini adalah fondasi yang sangat kuat untuk membangun fitur-fitur lain di masa depan.

Artikel Lainnya Dengan Kategori Terkait :


1. Inventaris Lab Laravel 12 : Bagian #01 - INSTALASI LARAGON, PHP, PHPMYADMIN & LARAVEL

2. Inventaris Lab Laravel 12 : Bagian #02 - KONFIGURASI DATABASE & FONDASI PROYEK

3. Inventaris Lab Laravel 12 : Bagian #03 - MEMBANGUN HALAMAN ADMIN DENGAN BLADE TEMPLATING

4. Inventaris Lab Laravel 12 : Bagian #04 - MEMBUAT HALAMAN DASHBOARD DINAMIS

5. Inventaris Lab Laravel 12 : Bagian #05 - MEMBUAT HALAMAN CRUD USERS

6. Inventaris Lab Laravel 12 : Bagian #06 - MEMBUAT FITUR AUTENTIKASI (LOGIN) & PENYESUAIAN UI

7. Inventaris Lab Laravel 12 : Bagian #07 - MEMBUAT HALAMAN CRUD CATEGORY

8. Inventaris Lab Laravel 12 : Bagian #08 - MEMBUAT HALAMAN CRUD ITEM

9. Inventaris Lab Laravel 12 : Bagian #09 - MEMBUAT HALAMAN TRANSAKSI PEMINJAMAN (LOAN)

10. Inventaris Lab Laravel 12 : Bagian #10 - HAK AKSES (AUTHORIZATION) & HALAMAN SISWA

Masuk Terlebih dahulu untuk berkomentar

Paling baru
Lihat Lainnya