(Part 3) Membuat Aplikasi POS (Point of Sales) Laravel 5.6 - Manajemen Produk

(Part 3) Membuat Aplikasi POS (Point of Sales) Laravel 5.6 - Manajemen Produk

Pendahuluan

Salah satu fitur penting dari aplikasi point of sales adalah manajemen produk, sebab data dari produk ini yang akan digunakan untuk proses transaksi nantinya. Jika sebelumnya kita telah membuat fitur manajemen kategori, dimana fitur ini berfungsi untuk mengelompokkan produk nantinya, maka pada tahap ini, yang perlu dikerjakan adalah table products agar terkait dengan pembahasan sebelumnya.

Ada masukan dari pembaca, bagaimana jika dalam fitur ini nantinya juga pengguna dapat melampirkan gambar dari produk yang dimilikinya namun sifatnya opsional. Nah, tentu saja ini masukan yang sangat baik (baca: terima kasih untuk masukkannya), sekaligus kita akan belajar bagaimana menambahkan field dari sebuah table jika dalam proses development terjadi perubahan informasi, salah satunya adalah penambahan fitur upload gambar.

Pada kasus ini adalah menambahkan fungsi upload gambar, lalu mari kita analisa. Apa yang diperlukan dari gambar ini? Mau seperti apa fitur yang diinginkan? Hanya satu gambar untuk masing-masing produk? Atau lebih dari satu? Jika ditarik kesimpulan, point of sales hanyalah sebuah aplikasi untuk melakukan proses transaksi penjualan sehingga gambar yang dibutuhkan hanya satu saja. Berbeda dengan e-commerce yang digunakan untuk menawarkan produk, sehingga lebih baik menggunakan banyak gambar agar calon konsumen dapat melihat produk tersebut dari berbagai sisi.

Karena yang dibutuhkan hanya satu gambar, lalu skemanya seperti apa? Secara pribadi saya lebih menyukai konsep, dimana gambar disimpan ke dalam folder, kemudian path dari gambar tersebut disimpan ke dalam database. Maka yang perlu dilakukan adalah dengan menambahkan field photo misalnya ke dalam table products.

Database Change

Konsepnya sudah dapat, maka untuk menambahkan field tersebut, tidak perlu lagi mengubah migration dari products. Yang perlu dilakukan adalah dengan membuat migration baru:

php artisan make:migration add_field_photo_to_products_table

Nama dari migration-nya, sekali lagi bebas tapi sebaiknya mewakili apa yang akan dilakukan dengan migration tersebut. Kemudian pada method Up tambahkan code berikut:

...
​
public function up()
{
    Schema::table('products', function(Blueprint $table) {
        $table->string('code')->unique()->after('id');
        $table->string('photo')->nullable()->after('category_id');
    });
}
​
...

Penjelasan: Menambahkan field photo kedalam table products dengan ketentuan nullable dan diletakkan setelah field category_id. Kita juga akan menambahkan code product yang nantinya akan digunakan untuk identifikasi product.

Jangan lupa untuk menjalankan command migrate agar migration yang terakhir kali ditambahkan dieksekusi

php artisan migrate

pos laravel - database change

View Data Produk

Sebenarnya apa yang akan kita lakukan disini, tidak jauh berbeda dari yang telah dilakukan sebelumnya. Letak perbedaannya hanya saja pada fitur ini, yang akan digunakan adalah dua table sekaligus, yakni table categories dan products. Skemanya adalah, dalam menampilkan data, tentu saja kita tidak akan menampilkan hanya ID Category saja, sebab sulit untuk di identifikasi oleh user, maka yang akan ditampilkan adalah nama dari kategori tersebut. Tapi kan, table yang akan digunakan nantinya adalah table products? Nah, disinilah kita akan belajar bagaimana menggunakan fitur eager loading dari Laravel.

Pertama, kita buat dulu layouts-nya. Generate controller dengan command:

php artisan make:controller ProductController

Buka file ProductController.php, kemudian tambahkan method berikut:

public function index()
{
    return view('products.index');
}

Penjelasan: Hanya sebuah method yang memanggil view dengan nama index.blade.php pada folder products.

Buat file index.blade.php di dalam resources/views/products

pos - produk folder

Kemudian masukkan tag html berikut:

@extends('layouts.master')
​
@section('title')
    <title>Manajemen Produk</title>
@endsection
​
@section('content')
    <div class="content-wrapper">
        <div class="content-header">
            <div class="container-fluid">
                <div class="row mb-2">
                    <div class="col-sm-6">
                        <h1 class="m-0 text-dark">Manajemen Produk</h1>
                    </div>
                    <div class="col-sm-6">
                        <ol class="breadcrumb float-sm-right">
                            <li class="breadcrumb-item"><a href="#">Home</a></li>
                            <li class="breadcrumb-item active">Produk</li>
                        </ol>
                    </div>
                </div>
            </div>
        </div>
​
        <section class="content">
            <div class="container-fluid">
                <div class="row">
                    <div class="col-md-12">
                        @card
                            @slot('title')
                            <a href="{{ route('produk.create') }}" 
                                class="btn btn-primary btn-sm">
                                <i class="fa fa-edit"></i> Tambah
                            </a>
                            @endslot
                            
                            @if (session('success'))
                                @alert(['type' => 'success'])
                                    {!! session('success') !!}
                                @endalert
                            @endif
                            
                            <div class="table-responsive">
                                <table class="table table-hover">
                                    <thead>
                                        <tr>
                                            <th>#</th>
                                            <th>Nama Produk</th>
                                            <th>Stok</th>
                                            <th>Harga</th>
                                            <th>Kategori</th>
                                            <th>Last Update</th>
                                            <th>Aksi</th>
                                        </tr>
                                    </thead>
                                    <tbody>
                                        <tr>
                                            <td></td>
                                            <td></td>
                                            <td></td>
                                            <td></td>
                                            <td></td>
                                            <td></td>
                                            <td></td>
                                        </tr>
                                    </tbody>
                                </table>
                            </div>
                            @slot('footer')
​
                            @endslot
                        @endcard
                    </div>
                </div>
            </div>
        </section>
    </div>
@endsection

Note: Tidak ada yang perlu dijelaskan karena hanya sebuah tag html.

Buka file routes/web.php kemudian tambahkan code:

Route::resource('/produk', 'ProductController');

Note: Menggunakan resources tanpa except karena kita akan menggunakan seluruh method yang telah disediakan.

Buka file resources/views/layouts/module/sidebar.blade.php Kemudian modifikasi pada tag untuk menu Produk:

<li class="nav-item">
     <a href="{{ route('produk.index') }}" class="nav-link">
         <i class="fa fa-circle-o nav-icon"></i>
         <p>Produk</p>
     </a>
 </li>

Note: Hanya menambahkan route('produk.index') agar menu produk bisa di klik untuk di arahkan ke halaman manajemen produk.

pos laravel - show product

Masih berupa layouts, jadi belum ada proses yang rumit sampai tahap ini, dan untuk sementara perlu kita skip, lalu melangkah ke fitur tambah produk karena belum ada data yang bisa kita tampilkan untuk saat ini. Jadi perlu untuk membuat fitur tambah data nya terlebih dahulu.

Create Data Produk

Tambahkan method create ke dalam file ProductController.php:

...
​
public function create()
{
    $categories = Category::orderBy('name', 'ASC')->get();
    return view('products.create', compact('categories'));
}
​
...

Penjelasan: Method ini berfungsi untuk menampilkan form tambah produk, dimana dalam form tersebut kita membutuhkan data kategori yang bisa dipilih nantinya dalam bentuk select box.

Pada line-3, menggunakan model Category untuk melakukan query select data dari table categories, Maka tambahkan use statement:

use App\Category;

Buat file create.blade.php di dalam folder resources/views/products, kemudian tambahkan code berikut:

@extends('layouts.master')
​
@section('title')
    <title>Tambah Data Produk</title>
@endsection
​
@section('content')
    <div class="content-wrapper">
        <div class="content-header">
            <div class="container-fluid">
                <div class="row mb-2">
                    <div class="col-sm-6">
                        <h1 class="m-0 text-dark">Tambah Data</h1>
                    </div>
                    <div class="col-sm-6">
                        <ol class="breadcrumb float-sm-right">
                            <li class="breadcrumb-item"><a href="#">Home</a></li>
                            <li class="breadcrumb-item"><a href="{{ route('produk.index') }}">Produk</a></li>
                            <li class="breadcrumb-item active">Tambah</li>
                        </ol>
                    </div>
                </div>
            </div>
        </div>
​
        <section class="content">
            <div class="container-fluid">
                <div class="row">
                    <div class="col-md-12">
                        @card
                            @slot('title')
                            
                            @endslot
                            
                            @if (session('success'))
                                @alert(['type' => 'success'])
                                    {!! session('success') !!}
                                @endalert
                            @endif
                            <form action="{{ route('produk.store') }}" method="post" enctype="multipart/form-data">
                                @csrf
                                <div class="form-group">
                                    <label for="">Kode Produk</label>
                                    <input type="text" name="code" required 
                                        maxlength="10"
                                        class="form-control {{ $errors->has('code') ? 'is-invalid':'' }}">
                                    <p class="text-danger">{{ $errors->first('code') }}</p>
                                </div>
                                <div class="form-group">
                                    <label for="">Nama Produk</label>
                                    <input type="text" name="name" required 
                                        class="form-control {{ $errors->has('name') ? 'is-invalid':'' }}">
                                    <p class="text-danger">{{ $errors->first('name') }}</p>
                                </div>
                                <div class="form-group">
                                    <label for="">Deskripsi</label>
                                    <textarea name="description" id="description" 
                                        cols="5" rows="5" 
                                        class="form-control {{ $errors->has('description') ? 'is-invalid':'' }}"></textarea>
                                    <p class="text-danger">{{ $errors->first('description') }}</p>
                                </div>
                                <div class="form-group">
                                    <label for="">Stok</label>
                                    <input type="number" name="stock" required 
                                        class="form-control {{ $errors->has('stock') ? 'is-invalid':'' }}">
                                    <p class="text-danger">{{ $errors->first('stock') }}</p>
                                </div>
                                <div class="form-group">
                                    <label for="">Harga</label>
                                    <input type="number" name="price" required 
                                        class="form-control {{ $errors->has('price') ? 'is-invalid':'' }}">
                                    <p class="text-danger">{{ $errors->first('price') }}</p>
                                </div>
                                <div class="form-group">
                                    <label for="">Kategori</label>
                                    <select name="category_id" id="category_id" 
                                        required class="form-control {{ $errors->has('price') ? 'is-invalid':'' }}">
                                        <option value="">Pilih</option>
                                        @foreach ($categories as $row)
                                            <option value="{{ $row->id }}">{{ ucfirst($row->name) }}</option>
                                        @endforeach
                                    </select>
                                    <p class="text-danger">{{ $errors->first('category_id') }}</p>
                                </div>
                                <div class="form-group">
                                    <label for="">Foto</label>
                                    <input type="file" name="photo" class="form-control">
                                    <p class="text-danger">{{ $errors->first('photo') }}</p>
                                </div>
                                <div class="form-group">
                                    <button class="btn btn-primary btn-sm">
                                        <i class="fa fa-send"></i> Simpan
                                    </button>
                                </div>
                            </form>
                            @slot('footer')
​
                            @endslot
                        @endcard
                    </div>
                </div>
            </div>
        </section>
    </div>
@endsection

Penjelasan: Dua hal yang perlu diperhatikan, Pertama, pada tag form terdapat enctype="multipart/form-data" yang berarti memberikan izin untuk mengirim file. Kedua, pada bagian tag select, terdapat code untuk me-looping data kategori, dimana id kategori yang akan dikirimkan untuk disimpan.

pos laravel - add product

Ketika tombol simpan ditekan masih akan terjadi error karena belum ada method untuk meng-handle data yang dikirimkan. Buka kembali ProductController.php, kemudian tambahkan method berikut:

...
    
public function store(Request $request)
{
    //validasi data
    $this->validate($request, [
        'code' => 'required|string|max:10|unique:products',
        'name' => 'required|string|max:100',
        'description' => 'nullable|string|max:100',
        'stock' => 'required|integer',
        'price' => 'required|integer',
        'category_id' => 'required|exists:categories,id',
        'photo' => 'nullable|image|mimes:jpg,png,jpeg'
    ]);
​
    try {
        //default $photo = null
        $photo = null;
        //jika terdapat file (Foto / Gambar) yang dikirim
        if ($request->hasFile('photo')) {
            //maka menjalankan method saveFile()
            $photo = $this->saveFile($request->name, $request->file('photo'));
        }

 
        //Simpan data ke dalam table products
        $product = Product::create([
            'code' => $request->code,
            'name' => $request->name,
            'description' => $request->description,
            'stock' => $request->stock,
            'price' => $request->price,
            'category_id' => $request->category_id,
            'photo' => $photo
        ]);
        
        //jika berhasil direct ke produk.index
        return redirect(route('produk.index'))
            ->with(['success' => '<strong>' . $product->name . '</strong> Ditambahkan']);
    } catch (\Exception $e) {
        //jika gagal, kembali ke halaman sebelumnya kemudian tampilkan error
        return redirect()->back()
            ->with(['error' => $e->getMessage()]);
    }
}
​
....

Penjelasan: Sebagian besar penjelasan sudah disematkan kedalam code diatas, yang perlu diperhatikan adalah bagian pemanggilan method saveFile(). Sengaja dipisahkan karena pada proses update data nantinya akan digunakan kembali. Jadi sekali buat code bisa digunakan berkali-kali.

Masih di dalam file ProductController.php, tambahkan method saveFile()

...
​
private function saveFile($name, $photo)
{
    //set nama file adalah gabungan antara nama produk dan time(). Ekstensi gambar tetap dipertahankan
    $images = str_slug($name) . time() . '.' . $photo->getClientOriginalExtension();
    //set path untuk menyimpan gambar
    $path = public_path('uploads/product');
​
    //cek jika uploads/product bukan direktori / folder
    if (!File::isDirectory($path)) {
        //maka folder tersebut dibuat
        File::makeDirectory($path, 0777, true, true);
    } 
    //simpan gambar yang diuplaod ke folrder uploads/produk
    Image::make($photo)->save($path . '/' . $images);
    //mengembalikan nama file yang ditampung divariable $images
    return $images;
}
​
...

Dari kedua method yang baru saja ditambahkan, perlu untuk menambahkan use statement untuk memanggil Facade File & Image, serta model Product:

use App\Product;
use File;
use Image;

Image merupakan facade yang digunakan dari library image intervention. So, kamu perlu untuk meng-install-nya dengan command:

composer require intervention/image

Terakhir, buka file app/Product.php kemudian tambahkan $guarded didalam class Product:

protected $guarded = [];

Fungsi untuk menyimpan data product ke dalam table products sudah selesai, maka kita akan melompat kembali ke sub topik View Data Produk

[Lanjut] View Data Produk

Karena sebelumnya masih berupa layouts karena data yang ingin ditampilkan belum ada, maka kembali kita akan melakukan perubahan agar data yang telah di-input bisa ditampilkan. Kembali ke method index dalam ProductController.php, modifikasi menjadi:

...
​
public function index()
{
    $products = Product::with('category')->orderBy('created_at', 'DESC')->paginate(10);
    return view('products.index', compact('products'));
}
​
...

Penjelasan: Query ini masih sama seperti sebelumnya, yang berbeda karena terdapat method with(). Fungsi dari method ini adalah untuk memanggil nama dari relasi yang telah didefinisikan. Darimana kata category? Kata ini diambil dari sebuah method yang telah didefinisikan didalam model Product. Lalu kenapa mesti di model Product? Karena dasarnya, kita menggunakan model Product untuk melakukan query ke database, maka secara otomatis hasil dari query tersebut akan menampilkan data category yang terkait.

Setelah dicek app\Product.php, method category kok belum ditemukan? Yah! Karena kita belum mendefinisikannya. Tambahkan method berikut didalam model Product.php:

public function category()
{
    return $this->belongsTo(Category::class);
}

Note: Untuk penjelasan mengenai relasi di Laravel, kamu dapat membaca artikel Mengenal Relationships di Laravel 5.4. Tambahan referensi lainnya kamu bisa baca Eloquent Relations: Mengurutkan Data di Laravel 5. Hal ini sudah pernah dibahas dalam artikel yang berbeda.

Buka file resources/views/products/index.blade.php, kemudian modifikasi tag table menjadi:

...
​
<tbody>
    @forelse ($products as $row)
    <tr>
        <td>
            @if (!empty($row->photo))
                <img src="{{ asset('uploads/product/' . $row->photo) }}" 
                    alt="{{ $row->name }}" width="50px" height="50px">
            @else
                <img src="http://via.placeholder.com/50x50" alt="{{ $row->name }}">
            @endif
        </td>
        <td>
            <sup class="label label-success">({{ $row->code }})</sup>
            <strong>{{ ucfirst($row->name) }}</strong>
        </td>
        <td>{{ $row->stock }}</td>
        <td>Rp {{ number_format($row->price) }}</td>
        <td>{{ $row->category->name }}</td>
        <td>{{ $row->updated_at }}</td>
        <td>
            <form action="{{ route('produk.destroy', $row->id) }}" method="POST">
                @csrf
                <input type="hidden" name="_method" value="DELETE">
                <a href="{{ route('produk.edit', $row->id) }}" 
                    class="btn btn-warning btn-sm">
                    <i class="fa fa-edit"></i>
                </a>
                <button class="btn btn-danger btn-sm">
                    <i class="fa fa-trash"></i>
                </button>
            </form>
        </td>
    </tr>
    @empty
    <tr>
        <td colspan="7" class="text-center">Tidak ada data</td>
    </tr>
    @endforelse
</tbody>
    
...

Penjelasan: Pada kolom pertama, mengecek jika photo tidak kosong maka gambar yang sudah di-upload akan di-load. Sedangkan jika kosong maka akan me-load gambar dari placeholder. Yang lain hanya menyesuaikan untuk menampilkan data sesuai kolomnya masing-masing.

Pada bagian {{ $row->category->name }}, mungkin teman-teman bertanya, kenapa ada category diantara name? Jika kita return hasil dari query-nya maka akan tampak seperti ini:

pos laravel - object query

Sebagaimana yang kita lihat, name dari category berada didalam object category. Sehingga untuk mengaksesnya adalah category->name.

Karena dalam query diatas menggunakan method paginate(), maka untuk me-render-nya, letakkan code berikut diluar tag table.

<div class="float-right">
    {!! $products->links() !!}
</div>

pos laravel - product view

Destroy Data Produk

Buka file ProductController.php, kemudian tambahkan method berikut:

...
    
public function destroy($id)
{
    //query select berdasarkan id
    $products = Product::findOrFail($id);
    //mengecek, jika field photo tidak null / kosong
    if (!empty($products->photo)) {
        //file akan dihapus dari folder uploads/produk
        File::delete(public_path('uploads/product/' . $products->photo));
    }
    //hapus data dari table
    $products->delete();
    return redirect()->back()->with(['success' => '<strong>' . $products->name . '</strong> Telah Dihapus!']);
}
​
...

Edit Data Produk

Konsep dari edit data, sekali lagi, tampilkan data yang akan di-edit kedalam form lalu di-update, jadi kita membutuhkan dua step. Masih didalam file ProductController.php, tambahkan method:

...
    
public function edit($id)
{
    //query select berdasarkan id
    $product = Product::findOrFail($id);
    $categories = Category::orderBy('name', 'ASC')->get();
    return view('products.edit', compact('product', 'categories'));
}
​
...

Penjelasan: Query untuk mengambil data dari table categories masih tetap dilakukan, karena edit data juga berarti bisa mengganti kategori produk.

Buat file edit.blade.php di dalam folder resources/views/products, kemudian masukkan code berikut:

@extends('layouts.master')
​
@section('title')
    <title>Edit Data Produk</title>
@endsection
​
@section('content')
    <div class="content-wrapper">
        <div class="content-header">
            <div class="container-fluid">
                <div class="row mb-2">
                    <div class="col-sm-6">
                        <h1 class="m-0 text-dark">Edit Data</h1>
                    </div>
                    <div class="col-sm-6">
                        <ol class="breadcrumb float-sm-right">
                            <li class="breadcrumb-item"><a href="#">Home</a></li>
                            <li class="breadcrumb-item"><a href="{{ route('produk.index') }}">Produk</a></li>
                            <li class="breadcrumb-item active">Edit</li>
                        </ol>
                    </div>
                </div>
            </div>
        </div>
​
        <section class="content">
            <div class="container-fluid">
                <div class="row">
                    <div class="col-md-12">
                        @card
                            @slot('title')
                            
                            @endslot
                            
                            @if (session('error'))
                                @alert(['type' => 'danger'])
                                    {!! session('error') !!}
                                @endalert
                            @endif
                            <form action="{{ route('produk.update', $product->id) }}" method="POST" enctype="multipart/form-data">
                                @csrf
                                <input type="hidden" name="_method" value="PUT">
                                <div class="form-group">
                                    <label for="">Kode Produk</label>
                                    <input type="text" name="code" required 
                                        maxlength="10"
                                        readonly
                                        value="{{ $product->code }}"
                                        class="form-control {{ $errors->has('code') ? 'is-invalid':'' }}">
                                    <p class="text-danger">{{ $errors->first('code') }}</p>
                                </div>
                                <div class="form-group">
                                    <label for="">Nama Produk</label>
                                    <input type="text" name="name" required 
                                        value="{{ $product->name }}"
                                        class="form-control {{ $errors->has('name') ? 'is-invalid':'' }}">
                                    <p class="text-danger">{{ $errors->first('name') }}</p>
                                </div>
                                <div class="form-group">
                                    <label for="">Deskripsi</label>
                                    <textarea name="description" id="description" 
                                        cols="5" rows="5" 
                                        class="form-control {{ $errors->has('description') ? 'is-invalid':'' }}">{{ $product->description }}</textarea>
                                    <p class="text-danger">{{ $errors->first('description') }}</p>
                                </div>
                                <div class="form-group">
                                    <label for="">Stok</label>
                                    <input type="number" name="stock" required 
                                        value="{{ $product->stock }}"
                                        class="form-control {{ $errors->has('stock') ? 'is-invalid':'' }}">
                                    <p class="text-danger">{{ $errors->first('stock') }}</p>
                                </div>
                                <div class="form-group">
                                    <label for="">Harga</label>
                                    <input type="number" name="price" required 
                                        value="{{ $product->price }}"
                                        class="form-control {{ $errors->has('price') ? 'is-invalid':'' }}">
                                    <p class="text-danger">{{ $errors->first('price') }}</p>
                                </div>
                                <div class="form-group">
                                    <label for="">Kategori</label>
                                    <select name="category_id" id="category_id" 
                                        required class="form-control {{ $errors->has('price') ? 'is-invalid':'' }}">
                                        <option value="">Pilih</option>
                                        @foreach ($categories as $row)
                                            <option value="{{ $row->id }}" {{ $row->id == $product->category_id ? 'selected':'' }}>
                                                {{ ucfirst($row->name) }}
                                            </option>
                                        @endforeach
                                    </select>
                                    <p class="text-danger">{{ $errors->first('category_id') }}</p>
                                </div>
                                <div class="form-group">
                                    <label for="">Foto</label>
                                    <input type="file" name="photo" class="form-control">
                                    <p class="text-danger">{{ $errors->first('photo') }}</p>
                                    @if (!empty($product->photo))
                                        <hr>
                                        <img src="{{ asset('uploads/product/' . $product->photo) }}" 
                                            alt="{{ $product->name }}"
                                            width="150px" height="150px">
                                    @endif
                                </div>
                                <div class="form-group">
                                    <button class="btn btn-info btn-sm">
                                        <i class="fa fa-refresh"></i> Update
                                    </button>
                                </div>
                            </form>
                            @slot('footer')
​
                            @endslot
                        @endcard
                    </div>
                </div>
            </div>
        </section>
    </div>
@endsection

Penjelasan: Yang perlu diperhatikan hanya pada bagian <option value="{{ $row->id }}" {{ $row->id == $product->category_id ? 'selected':'' }}> dimana menggunakan ternary operator, apabila kondisinya terpenuhi maka selected akan ditambahkan, jika tidak tetap kosong. Selain itu, code product dibaut readonly karena code tersebut tidak akan di-edit.

Buka file ProductController.php, kemudian tambah method update:

public function update(Request $request, $id)
{
    //validasi
    $this->validate($request, [
        'code' => 'required|string|max:10|exists:products,code',
        'name' => 'required|string|max:100',
        'description' => 'nullable|string|max:100',
        'stock' => 'required|integer',
        'price' => 'required|integer',
        'category_id' => 'required|exists:categories,id',
        'photo' => 'nullable|image|mimes:jpg,png,jpeg'
    ]);
​
    try {
        //query select berdasarkan id
        $product = Product::findOrFail($id);
        $photo = $product->photo;

 
        //cek jika ada file yang dikirim dari form
        if ($request->hasFile('photo')) {
            //cek, jika photo tidak kosong maka file yang ada di folder uploads/product akan dihapus
            !empty($photo) ? File::delete(public_path('uploads/product/' . $photo)):null;
            //uploading file dengan menggunakan method saveFile() yg telah dibuat sebelumnya
            $photo = $this->saveFile($request->name, $request->file('photo'));
        }

 
        //perbaharui data di database
        $product->update([
            'name' => $request->name,
            'description' => $request->description,
            'stock' => $request->stock,
            'price' => $request->price,
            'category_id' => $request->category_id,
            'photo' => $photo
        ]);
​
        return redirect(route('produk.index'))
            ->with(['success' => '<strong>' . $product->name . '</strong> Diperbaharui']);
    } catch (\Exception $e) {
        return redirect()->back()
            ->with(['error' => $e->getMessage()]);
    }
}

Note: Penjelasan sudah disematkan di dalam code, sedikit tambahan bahwa flow yang dilakukan terhadap gambar apabila terdapat file yang dikirim dari form adalah menghapus file gambar yang lama agar tidak terjadi penumpukan gambar, yang sebenarnya sudah tidak digunakan.

Kesimpulan

Perbedaan yang mencolok dari fitur manajemen produk dibandingkan manajemen kategori adalah penggunaan dua buah table (Model), karena sebagaimana yang terlihat dari struktur database yang terdapat di dalam table products, membutuhkan category_id untuk mengelompokkan produk, sehingga nantinya dapat di-filter dengan mudah.

Sebenarnya masih ada hal yang perlu dilakukan dalam sesi ini, yakni menampilkan detail produk. Akan tetapi saya menginginkan detail produk tersebut ditampilkan dalam bentuk modal, maka fitur ini akan dipindahkan pada materi yang menggunakan ajax request.

Dokumentasi source code-nya dapat kamu lihat di Github.

Category:
Share:

Comments