Aplikasi E-Commerce Laravel 6 #3: Management Category (CRUD)

Aplikasi E-Commerce Laravel 6 #3: Management Category (CRUD)

Pendahuluan

Istilah CRUD adalah lompatan awal yang dijadikan tujuan kebanyakan orang dalam belajar bahasa pemrograman. Saya tipe orang yang setuju bahwa tidak semua aplikasi dibangun dengan potongan-potongan CRUD tapi banyak aplikasi yang dirangkai dari potongan-potongan CRUD.

Lalu pertanyaannya adalah CRUD itu apa? Kalau saya membahasakannya secara sederhana adalah seni memanipulasi database karena terdiri dari Create, Read, Update & Delete. Kata kunci ini menjadi sangat familiar ketika seseorang belajar sebuah bahasa pemrograman dan karena sudah familiar maka kita akan menggunakan pondasi ini untuk mengenali cara kerja Laravel.

Berangkat dari sebuah modul sederhana yakni Management Category, kita akan membuat serangkaian proses yang akan membentuk sebuah fitur baru untuk memanipulasi data kategori yang terdiri dari proses menambahkan data, edit data, hapus data dan menampilkan data yang ada.

Baca Juga: Aplikasi E-Commerce Laravel 6 #2: Templating & Authentication

Show List of Categories

Konsep sederhana dalam menampilkan data adalah dengan mengambil semua data terkait dari database kemudian data tersebut diteruskan ke-view untuk ditampilkan kepada users yang sedang menggunakan aplikasi tersebut.

Note: Gambarnya salah, harusnya http://localhost:8000/administrator/category.

Gambaran sederhananya sudah didapatkan, maka saatnya untuk direalisasikan kedalam codingan. Pertama, buat routingnya terlebih dahulu dengan membuka file routes/web.php dan modifikasi menjadi

<?php

/*
|--------------------------------------------------------------------------
| 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');
});

Auth::routes();

//JADI INI GROUPING ROUTE, SEHINGGA SEMUA ROUTE YANG ADA DIDALAMNYA
//SECARA OTOMATIS AKAN DIAWALI DENGAN administrator
//CONTOH: /administrator/category ATAU /administrator/product, DAN SEBAGAINYA
Route::group(['prefix' => 'administrator', 'middleware' => 'auth'], function() {
    Route::get('/home', 'HomeController@index')->name('home'); //JADI ROUTING INI SUDAH ADA DARI ARTIKEL SEBELUMNYA TAPI KITA PINDAHKAN KEDALAM GROUPING

    //INI ADALAH ROUTE BARU
    Route::resource('category', 'CategoryController')->except(['create', 'show']);
});

Penjelasan: Karena ini adalah CRUD maka Laravel sendiri sudah mencakup proses tersebut dengan menyediakan 1 buah route yang terdiri dari 7 buah route. Jika kita menggunakan resource(), maka sama saja kita sudah mendefinisikan 7 buah route.

Sebagai contoh, sebaris route baru diatas sama dengan code dibawah ini

Route::get('/category', 'CategoryController@index')->name('category.index');
Route::post('/category', 'CategoryController@store')->name('category.store');
Route::get('/category/{category_id}/edit', 'CategoryController@edit')->name('category.edit');
Route::put('/category/{category_id}', 'CategoryController@update')->name('category.update');
Route::delete('/category/{category_id}', 'CategoryController@destroy')->name('category.destroy');

Note: Tidak perlu dituliskan karena hanya penjabaran dari fungsi resources.

Kok hanya 5 route? Perhatikan code except(['create', 'show']) pada akhir baris yang dikecualikan, semestinya codingan-nya untuk 2 route tersebut adalah:

Route::get('/category/{category_id}', 'CategoryController@show')->name('category.show');
Route::get('/category/create', 'CategoryController@create')->name('category.create');

Note: Tidak perlu dituliskan karena hanya penjabaran dari fungsi resources.

Perhatikan route /category yang bertipe GET akan mengakses method index() pada CategoryController, maka pada command line, generate controller baru dengan command

php artisan make:controller CategoryController

Kemudian buka file CategoryController.php dan modifikasi menjadi:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Category; //LOAD MODEL CATEGORY

class CategoryController extends Controller
{
    public function index()
    {
        //BUAT QUERY KE DATABASE MENGGUNAKAN MODEL CATEGORY DENGAN MENGURUTKAN BERDASARKAN CREATED_AT DAN DISET DESCENDING, KEMUDIAN PAGINATE(10) BERARTI HANYA ME-LOAD 10 DATA PER PAGENYA
        //YANG MENARIK ADALAH FUNGSI WITH(), DIMANA FUNGSI INI DISEBUT EAGER LOADING
        //ADAPUN NAMA YANG DISEBUTKAN DIDALAMNYA ADALAH NAMA METHOD YANG DIDEFINISIKAN DIDALAM MODEL CATEGORY
        //METHOD TERSEBUT BERISI FUNGSI RELATIONSHIPS ANTAR TABLE
        //JIKA LEBIH DARI 1 MAKA DAPAT DIPISAHKAN DENGAN KOMA, 
        // CONTOH: with(['parent', 'contoh1', 'contoh2'])
        $category = Category::with(['parent'])->orderBy('created_at', 'DESC')->paginate(10);
      
        //QUERY INI MENGAMBIL SEMUA LIST CATEGORY DARI TABLE CATEGORIES, PERHATIKAN AKHIRANNYA ADALAH GET() TANPA ADA LIMIT
        //LALU getParent() DARI MANA? METHOD TERSEBUT ADALAH SEBUAH LOCAL SCOPE
        $parent = Category::getParent()->orderBy('name', 'ASC')->get();
      
        //LOAD VIEW DARI FOLDER CATEGORIES, DAN DIDALAMNYA ADA FILE INDEX.BLADE.PHP
        //KEMUDIAN PASSING DATA DARI VARIABLE $category & $parent KE VIEW AGAR DAPAT DIGUNAKAN PADA VIEW TERKAIT
        return view('categories.index', compact('category', 'parent'));
    }
  
    //METHOD LAINNYA DISINI JIKA ADA
}

Note: Penjelasan local scope akan dijelaskan kemudian.

Sebelum melangkah ke proses pembuatan file view, maka ada dua bagian yang perlu dilengkapi, pertama adalah method parent() dan local scope getParent() pada model Category.php. Buka file Category.php dan tambahkan kedua method berikut

//INI ADALAH METHOD UNTUK MENG-HANDLE RELATIONSHIPS
public function parent()
{
    //KARENA RELASINYA DENGAN DIRINYA SENDIRI, MAKA CLASS MODEL DIDALM belongsTo() ADALAH NAMA CLASSNYA SENDIRI YAKNI CATEGORY
    //belongsTo DIGUNAKAN UNTUK REFLEKSI KE DATA INDUKNYA
    return $this->belongsTo(Category::class);
}

//UNTUK LOCAL SCOPE NAMA METHODNYA DIAWAL DENGAN KATA scope DAN DIIKUTI DENGAN NAMA METHOD YANG DIINGINKAN
//CONTOH: scopeNamaMethod()
public function scopeGetParent($query)
{
    //SEMUA QUERY YANG MENGGUNAKAN LOCAL SCOPE INI AKAN SECARA OTOMATIS DITAMBAHKAN KONDISI whereNul('parent_id')
    return $query->whereNull('parent_id');
}

Note: Local scope digunakan untuk mengelompokkan query yang bisa digunakan kembali pada kondisi lain sehingga kita tidak perlu menuliskan kembali query tersebut.

Selanjutnya buat file index.blade.php di dalam folder resources/views/categories (red: jika folder categories belum ada, silahkan dibuat) dan tambahkan code berikut.

<!-- MEMANGGIL MASTER TEMPLATE YANG SUDAH DIBUAT SEBELUMNYA, YAKNI admin.blade.php -->
@extends('layouts.admin')

@section('title')
    <title>List Kategori</title>
@endsection

@section('content')
<main class="main">
    <ol class="breadcrumb">
        <li class="breadcrumb-item">Home</li>
        <li class="breadcrumb-item active">Kategori</li>
    </ol>
    <div class="container-fluid">
        <div class="animated fadeIn">
            <div class="row">
              	
              	<!-- BAGIAN INI AKAN MENG-HANDLE FORM INPUT NEW CATEGORY  -->
                <div class="col-md-4">
                    <div class="card">
                        <div class="card-header">
                            <h4 class="card-title">Kategori Baru</h4>
                        </div>
                        <div class="card-body">
                          
                            <!-- PADA SUB-CHAPTER SELANJUTNYA, KETIKA ADA INSTRUKSI UNTUK ME-REPLACE FORM INPUT NEW CATEGORY MAKA CARI KOMENTAR INI DAN REPLACE DENGAN CODE YANG ADA DISANA -->
                          
                        </div>
                    </div>
                </div>
                <!-- BAGIAN INI AKAN MENG-HANDLE FORM INPUT NEW CATEGORY  -->
              
                <!-- BAGIAN INI AKAN MENG-HANDLE TABLE LIST CATEGORY  -->
                <div class="col-md-8">
                    <div class="card">
                        <div class="card-header">
                            <h4 class="card-title">List Kategori</h4>
                        </div>
                        <div class="card-body">
                          	<!-- KETIKA ADA SESSION SUCCESS  -->
                            @if (session('success'))
                              <!-- MAKA TAMPILKAN ALERT SUCCESS -->
                                <div class="alert alert-success">{{ session('success') }}</div>
                            @endif

                            <!-- KETIKA ADA SESSION ERROR  -->
                            @if (session('error'))
                              <!-- MAKA TAMPILKAN ALERT DANGER -->
                                <div class="alert alert-danger">{{ session('error') }}</div>
                            @endif

                            <div class="table-responsive">
                                <table class="table table-hover table-bordered">
                                    <thead>
                                        <tr>
                                            <th>#</th>
                                            <th>Kategori</th>
                                            <th>Parent</th>
                                            <th>Created At</th>
                                            <th>Aksi</th>
                                        </tr>
                                    </thead>
                                    <tbody>
                                      	<!-- LOOPING DATA KATEGORI SESUAI JUMLAH DATA YANG ADA DI VARIABLE $CATEGORY -->
                                        @forelse ($category as $val)
                                        <tr>
                                            <td></td>
                                            <td><strong>{{ $val->name }}</strong></td>
                                          
                                          	<!-- MENGGUNAKAN TERNARY OPERATOR, UNTUK MENGECEK, JIKA $val->parent ADA MAKA TAMPILKAN NAMA PARENTNYA, SELAIN ITU MAKA TANMPILKAN STRING - -->
                                            <td>{{ $val->parent ? $val->parent->name:'-' }}</td>
                                          
                                            <!-- FORMAT TANGGAL KETIKA KATEGORI DIINPUT SESUAI FORMAT INDONESIA -->
                                            <td>{{ $val->created_at->format('d-m-Y') }}</td>
                                            <td>
                                              
                                                <!-- FORM ACTION UNTUK METHOD DELETE -->
                                                <form action="{{ route('category.destroy', $val->id) }}" method="post">
                                                    <!-- KONVERSI DARI @ CSRF & @ METHOD AKAN DIJELASKAN DIBAWAH -->
                                                    @csrf
                                                    @method('DELETE')
                                                    <a href="{{ route('category.edit', $val->id) }}" class="btn btn-warning btn-sm">Edit</a>
                                                    <button class="btn btn-danger btn-sm">Hapus</button>
                                                </form>
                                            </td>
                                        </tr>
                                        <!-- JIKA DATA CATEGORY KOSONG, MAKA AKAN DIRENDER KOLOM DIBAWAH INI  -->
                                        @empty
                                        <tr>
                                            <td colspan="5" class="text-center">Tidak ada data</td>
                                        </tr>
                                        @endforelse
                                    </tbody>
                                </table>
                            </div>
                            <!-- FUNGSI INI AKAN SECARA OTOMATIS MEN-GENERATE TOMBOL PAGINATION  -->
                            {!! $category->links() !!}
                        </div>
                    </div>
                </div>
                <!-- BAGIAN INI AKAN MENG-HANDLE TABLE LIST CATEGORY  -->
            </div>
        </div>
    </div>
</main>
@endsection

Ada 3 buah konversi yang akan dijelaskan sebelum melangkah ke-tahap selanjutnya, jadi code dibawah ini tidak perlu dituliskan karena hanya berupa konversi dari code diatas kedalam code yang mungkin kamu kenali.

Pertama adalah @forelse() adalah sebuah directive dari Laravel yang jika dikonversi menjadi code PHP biasa akan menjadi:

<?php

if (count($category) > 0) {
	foreach ($category as $val) {
		//TAMPILANNYA DISINI
	}
} else {
  //TAMPILANNYA DISINI
}

Bagian kedua adalah @csrf adalah directive lainnya dari Laravel untuk men-generate sebuah input-an yang berisi string random, maka jika kita konversi menjadi html code adalah

<input type="hidden" name="_token" value="STRING RANDOMNYA DISINI SECARA OTOMATIS"> 

Note: _token adalah data yang wajib dikirimkan untuk semua request yang bersifat mengubah seperti POST, PUT dan DELETE. Sebenarnya permintaan ini bisa dihilangkan dengan menambahkan url routing anda pada file app/Http/Middleware/VerifyCsrfToken.php dan tepatnya didalam array property $except.

Bagian terakhir dari konversi ini adalah @method yang juga merupakan directive untuk men-generate HTML code, yang jika kita konversi menjadi

<input type="hidden" name="_method" value="DELETE">

Note: Value yang ada didalam @method('DISINI') akan secara otomatis mengisi ruang pada bagian value yang ada di-tag HTML diatas.

Add Link Sidebar Menu

Agar halaman kategori bisa diakses hanya dengan meng-klik menu kategori yang ada pada sidebar menu, maka kita perlu menambahkan link-nya. Buka file sidebar.blade.php yang berada didalam folder resources/views/layouts/module dan modifikasi bagian berikut

<li class="nav-item">
    <a class="nav-link" href="{{ route('category.index') }}">
        <i class="nav-icon icon-drop"></i> Kategori
    </a>
</li>

Add New Category

Fitur untuk Menambahkan data kategori baru adalah tujuan kita selanjutnya, konsepnya juga sederhana dimana user mengirimkan form request melalui browser kemudian permintaan tersebut akan diolah dan datanya disimpan kedalam table categories. Setelah proses penyimpanan berhasil, maka akan di-redirect ke halaman list category.

Untuk merealisasikan gambaran diatas kedalam codingan, maka ada beberapa bagian yang akan dikerjakan. Bagian pertama seharusnya adalah routing, akan tetapi sudah diwakilkan oleh Route::resource() yang telah men-generate beberapa route sekaligus. Maka tugas selanjutnya adalah membuat method store(), buka file CategoryController.php dan tambahkan method berikut

public function store(Request $request)
{
    //JADI KITA VALIDASI DATA YANG DITERIMA, DIMANA NAME CATEGORY WAJIB DIISI
    //TIPENYA ADA STRING DAN MAX KARATERNYA ADALAH 50 DAN BERSIFAT UNIK
    //UNIK MAKSUDNYA JIKA DATA DENGAN NAMA YANG SAMA SUDAH ADA MAKA VALIDASINYA AKAN MENGEMBALIKAN ERROR
    $this->validate($request, [
        'name' => 'required|string|max:50|unique:categories'
    ]);

    //FIELD slug AKAN DITAMBAHKAN KEDALAM COLLECTION $REQUEST
    $request->request->add(['slug' => $request->name]);
  
    //SEHINGGA PADA BAGIAN INI KITA TINGGAL MENGGUNAKAN $request->except()
    //YAKNI MENGGUNAKAN SEMUA DATA YANG ADA DIDALAM $REQUEST KECUALI INDEX _TOKEN
    //FUNGSI REQUEST INI SECARA OTOMATIS AKAN MENJADI ARRAY
    //CATEGORY::CREATE ADALAH MASS ASSIGNMENT UNTUK MEMBERIKAN INSTRUKSI KE MODEL AGAR MENAMBAHKAN DATA KE TABLE TERKAIT
    Category::create($request->except('_token'));
    //APABILA BERHASIL, MAKA REDIRECT KE HALAMAN LIST KATEGORI
    //DAN MEMBUAT FLASH SESSION MENGGUNAKAN WITH()
    //JADI WITH() DISINI BERBEDA FUNGSINYA DENGAN WITH() YANG DISAMBUNGKAN DENGAN MODEL
    return redirect(route('category.index'))->with(['success' => 'Kategori Baru Ditambahkan!']);
}

Fungsi mass assignment diatas akan mengalami error jika field yang ada, tidak diizinkan untuk menyimpan data, maka buka file model app/Category.php dan tambahkan code berikut:

protected $fillable = ['name', 'parent_id', 'slug'];

Note: Masukkan semua field yang ingin kamu izinkan untuk dimodifikasi datanya. Lalu apa perbedaannya dengan property $guarded? Sabar, materi ini akan dibahas dilain waktu.

Masih dengan file yang sama, tambahkan method berikut

//MUTATOR
public function setSlugAttribute($value)
{
    $this->attributes['slug'] = Str::slug($value);
}

//ACCESSOR
public function getNameAttribute($value)
{
    return ucfirst($value);
}

Penjelasan: Fungsi diatas disebut Mutator, dimana fungsi tersebut bekerja untuk memodifikasi data sebelum data tersebut disimpan kedalam database. Contohnya adalah value dari slug akan diubah formatnya menjadi slug (red: formatnya adalah dengan menambahkan - pada semua spasi) menggunakan helper Str::slug(), mutator sendiri memiliki karakter nama method-nya adalah setNamaFieldAttribute(). Sedangkan Accessor berlaku sebaliknya, formatting-nya dilakukan setelah data diterima dari database dan karakter nama method-nya adalah getNamaFieldAttribute().

Jangan lupa tambahkan use statement dibawah ini

use Illuminate\Support\Str;

Lalu pertanyaanya adalah form input-annya mana? Nah! Kini saatnya kita me-replace komentar yang ada file resources/views/categories/index.blade.php dengan code

<form action="{{ route('category.store') }}" method="post">
    @csrf
    <div class="form-group">
        <label for="name">Kategori</label>
        <input type="text" name="name" class="form-control" required>
        <p class="text-danger">{{ $errors->first('name') }}</p>
    </div>
    <div class="form-group">
        <label for="parent_id">Kategori</label>
      	<!-- VARIABLE $PARENT PADA METHOD INDEX KITA GUNAKAN DISINI -->
        <!-- UNTUK MENAMPILKAN DATA CATEGORY YANG PARENT_ID NYA NULL -->
        <!-- UNTUK DIPILIH SEBAGAI PARENT TAPI SIFATNYA OPTIONAL -->
        <select name="parent_id" class="form-control">
            <option value="">None</option>
            @foreach ($parent as $row)
            <option value="{{ $row->id }}">{{ $row->name }}</option>
            @endforeach
        </select>
        <p class="text-danger">{{ $errors->first('name') }}</p>
    </div>
    <div class="form-group">
        <button class="btn btn-primary btn-sm">Tambah</button>
    </div>
</form>

Note: Ingat!, Cari komentar ini dan replace dengan code diatas <!-- PADA SUB-CHAPTER SELANJUTNYA, KETIKA ADA INSTRUKSI UNTUK ME-REPLACE FORM INPUT NEW CATEGORY MAKA CARI KOMENTAR INI DAN REPLACE DENGAN CODE YANG ADA DISANA -->

Form Edit Category

Ada dua langkah untuk mengubah data yang sudah ada, pertama adalah menampilkan form untuk mengedit data tersebut dan selanjutnya adalah proses untuk mengubah data terkait. Pada bagian ini kita akan mengambil data kategori berdasarkan id-nya kemudian ditampilkan pada sebuah form agar user bisa mengubah datanya.

Routing-nya sudah ada, maka tugas kita adalah membuat method yang didalamnya terdapat query untuk mengambil data. Buka file CategoryController.php dan tambahkan code berikut

public function edit($id)
{
    $category = Category::find($id); //QUERY MENGAMBIL DATA BERDASARKAN ID
    $parent = Category::getParent()->orderBy('name', 'ASC')->get(); //INI SAMA DENGAN QUERY YANG ADA PADA METHOD INDEX
  
    //LOAD VIEW EDIT.BLADE.PHP PADA FOLDER CATEGORIES
    //DAN PASSING VARIABLE CATEGORY & PARENT
    return view('categories.edit', compact('category', 'parent'));
}

Kemudian buat file edit.blade.php didalam folder resources/views/categories/edit.blade.php dan tambahkan code dibawah ini

@extends('layouts.admin')

@section('title')
    <title>Edit Kategori</title>
@endsection

@section('content')
<main class="main">
    <ol class="breadcrumb">
        <li class="breadcrumb-item">Home</li>
        <li class="breadcrumb-item active">Edit Kategori</li>
    </ol>
    <div class="container-fluid">
        <div class="animated fadeIn">
            <div class="row">
                <div class="col-md-8">
                    <div class="card">
                        <div class="card-header">
                            <h4 class="card-title">Edit Kategori</h4>
                        </div>
                        <div class="card-body">
                          	<!-- ROUTINGNYA MENGIRIMKAN ID CATEGORY YANG AKAN DIEDIT -->
                            <form action="{{ route('category.update', $category->id) }}" method="post">
                                @csrf
                                @method('PUT')
                                 
                                <div class="form-group">
                                    <label for="name">Kategori</label>
                                    <input type="text" name="name" class="form-control" value="{{ $category->name }}" required>
                                    <p class="text-danger">{{ $errors->first('name') }}</p>
                                </div>
                                <div class="form-group">
                                    <label for="parent_id">Kategori</label>
                                    <select name="parent_id" class="form-control">
                                        <option value="">None</option>
                                        @foreach ($parent as $row)
                                      
                                      	<!-- TERDAPAT TERNARY OPERATOR UNTUK MENGECEK JIKA PARENT_ID SAMA DENGAN ID CATEGORY PADA LIST PARENT, MAKA OTOMATIS SELECTED -->
                                        <option value="{{ $row->id }}" {{ $category->parent_id == $row->id ? 'selected':'' }}>{{ $row->name }}</option>
                                        @endforeach
                                    </select>
                                    <p class="text-danger">{{ $errors->first('name') }}</p>
                                </div>
                                <div class="form-group">
                                    <button class="btn btn-primary btn-sm">Simpan</button>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</main>
@endsection

Note: Selebihnya hanya tag html biasa.

Update Data Category

Ketika tombol simpan ditekan pada form edit, maka akan mengirimkan request untuk mengubah data pada database berdasarkan data yang dikirimkan. Prosesnya adalah melakukan query untuk mencari data terkait berdasarkan id-nya dan memperbaharui data tersebut.

Buka file CategoryController.php dan tambahkan method dibawah ini

public function update(Request $request, $id)
{
    //VALIDASI FIELD NAME
    //YANG BERBEDA ADA TAMBAHAN PADA RULE UNIQUE
    //FORMATNYA ADALAH unique:nama_table,nama_field,id_ignore
    //JADI KITA TETAP MENGECEK UNTUK MEMASTIKAN BAHWA NAMA CATEGORYNYA UNIK
    //AKAN TETAPI KHUSUS DATA DENGAN ID YANG AKAN DIUPDATE DATANYA DIKECUALIKAN
    $this->validate($request, [
        'name' => 'required|string|max:50|unique:categories,name,' . $id
    ]);

    $category = Category::find($id); //QUERY UNTUK MENGAMBIL DATA BERDASARKAN ID
    //KEMUDMIAN PERBAHARUI DATANYA
    //POSISI KIRI ADALAH NAMA FIELD YANG ADA DITABLE CATEGORIES
    //POSISI KANAN ADALAH VALUE DARI FORM EDIT
    $category->update([
        'name' => $request->name,
        'parent_id' => $request->parent_id
    ]);
  
    //REDIRECT KE HALAMAN LIST KATEGORI
    return redirect(route('category.index'))->with(['success' => 'Kategori Diperbaharui!']);
}

Karena routing-nya sudah ada maka sub-bab ini selesai sampai disini karena tugas kita hanya meng-handle data yang diterima dari form request untuk diolah lebih lanjut dimana dalam hal ini adalah memperbaharui data tersebut.

Delete Category

Sub-bab ini terbilang cukup singkat karena tombol delete beserta form-nya sudah dikerjakan pada sub-bab list categories, dimana schema yang diinginkan adalah ketika user menekan tombol delete maka akan mengirimkan form request dengan method DELETE beserta id category yang akan dihapus pada url.

Apabila direalisasikan, buka file CategoryController.php dan tambahkan method

public function destroy($id)
{
    //Buat query untuk mengambil category berdasarkan id menggunakan method find()
    //ADAPUN withCount() SERUPA DENGAN EAGER LOADING YANG MENGGUNAKAN with()
    //HANYA SAJA withCount() RETURNNYA ADALAH INTEGER
    //JADI NNTI HASIL QUERYNYA AKAN MENAMBAHKAN FIELD BARU BERNAMA child_count YANG BERISI JUMLAH DATA ANAK KATEGORI
    $category = Category::withCount(['child'])->find($id);
    //JIKA KATEGORI INI TIDAK DIGUNAKAN SEBAGAI PARENT ATAU CHILDNYA = 0
    if ($category->child_count == 0) {
        //MAKA HAPUS KATEGORI INI
        $category->delete();
        //DAN REDIRECT KEMBALI KE HALAMAN LIST KATEGORI
        return redirect(route('category.index'))->with(['success' => 'Kategori Dihapus!']);
    }
    //SELAIN ITU, MAKA REDIRECT KE LIST TAPI FLASH MESSAGENYA ERROR YANG BERARTI KATEGORI INI SEDANG DIGUNAKAN
    return redirect(route('category.index'))->with(['error' => 'Kategori Ini Memiliki Anak Kategori!']);
}

Method child ini tentu saja berasal dari model, maka buka file Category.php dan tambahkan method

public function child()
{
    //MENGGUNAKAN RELASI ONE TO MANY DENGAN FOREIGN KEY parent_id
    return $this->hasMany(Category::class, 'parent_id');
}

Lalu route-nya gimana? Sekali lagi tenang, kan sudah di-generate dengan Route::resource().

[Solve] Login Redirect

Masalah baru muncul ketika kita melalukan perubahan pada struktur routing, dimana route Route::get('/home', 'HomeController@index')->name('home'); kita masukkan kedalam group dengan prefix administrator dan masalah yang ditimbulkan adalah ketika redirect setelah login berhasil, dimana halaman yang dituju adalah /home, sedangkan halaman tersebut sudah tidak ada. Maka untuk menyelesaikan permasalahan tersebut, maka kita harus menyesuaikan path yang seharusnya dituju ketika login berhasil.

Pertama, buka file LoginController.php yang berada didalam folder app/Http/Controllers/Auth dan ubah property $redirectTo menjadi

protected $redirectTo = '/administrator/home';

Bagian kedua adalah Middleware yang mendeteksi user sudah login atau belum. Buka file RedirectIfAuthenticated.php yang berada didalam folder app/Http/Middleware dan modifikasi method handle() menjadi:

public function handle($request, Closure $next, $guard = null)
{
    if (Auth::guard($guard)->check()) {
        return redirect('/administrator/home'); //UBAH BAGIAN INI
    }

    return $next($request);
}

Baca Juga: Aplikasi E-Commerce Laravel 6 #1: Schema Database

Kesimpulan

Bermodalkan pemahaman bagaimana membuat CRUD di Laravel adalah sebuah langkah awal yang bisa dijadikan dasar dalam mengerjakan modul lainnya dengan tingkatan yang sedikit kompleks. Penulis berharap kamu mengulang materi ini beberapa kali hingga paham betul bagaimana alur penggunaannya. Sebab ngoding bukan hanya sekedar bisa berjalan sesuai yang diinginkan akan tetapi paham bagaimana dia bekerja sehingga apabila kita dihadapkan dengan case yang berbeda maka kita bisa menyelesaikannya secara mandiri.

Adapun dokumentasi code dari artikel ini bisa kamu lihat di Github.

Category:
Share:

Comments