Press ESC to close

Tutorial Update Data di Laravel 11: Edit dan Validasi Form – CRUD #4

Pendahuluan

Setelah berhasil mengimplementasikan operasi Create dan Read, kini kita akan mempelajari cara mengupdate data produk. Tutorial ini akan mencakup pembuatan form edit, validasi data, dan best practices dalam melakukan operasi update.

Langkah 1: Update ProductController

Tambahkan method edit dan update di app/Http/Controllers/ProductController.php:

namespace App\Http\Controllers;

use App\Models\Product;
use Illuminate\Http\Request;

class ProductController extends Controller
{
    // ... methods sebelumnya ...

    public function edit(Product $product)
    {
        return view('products.edit', compact('product'));
    }

    public function update(Request $request, Product $product)
    {
        $request->validate([
            'name' => 'required|max:255',
            'description' => 'required',
            'price' => 'required|numeric|min:0',
            'stock' => 'required|integer|min:0'
        ]);

        $product->update($request->all());

        return redirect()->route('products.index')
            ->with('success', 'Produk berhasil diperbarui!');
    }
}

Langkah 2: Membuat Form Request untuk Validasi

Untuk validasi yang lebih terorganisir, buat Request class khusus:

php artisan make:request UpdateProductRequest

Edit file app/Http/Requests/UpdateProductRequest.php:

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class UpdateProductRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'name' => 'required|max:255',
            'description' => 'required',
            'price' => 'required|numeric|min:0',
            'stock' => 'required|integer|min:0'
        ];
    }

    public function messages()
    {
        return [
            'name.required' => 'Nama produk harus diisi',
            'name.max' => 'Nama produk maksimal 255 karakter',
            'description.required' => 'Deskripsi produk harus diisi',
            'price.required' => 'Harga produk harus diisi',
            'price.numeric' => 'Harga harus berupa angka',
            'price.min' => 'Harga tidak boleh negatif',
            'stock.required' => 'Stok produk harus diisi',
            'stock.integer' => 'Stok harus berupa angka bulat',
            'stock.min' => 'Stok tidak boleh negatif'
        ];
    }
}

Update controller untuk menggunakan Request class:

use App\Http\Requests\UpdateProductRequest;

public function update(UpdateProductRequest $request, Product $product)
{
    $product->update($request->validated());

    return redirect()->route('products.index')
        ->with('success', 'Produk berhasil diperbarui!');
}

Langkah 3: Membuat View Form Edit

Buat file resources/views/products/edit.blade.php:

@extends('layouts.app')

@section('content')
<div class="container mx-auto px-4 py-8">
    <div class="max-w-2xl mx-auto">
        <div class="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4">
            <h1 class="text-2xl font-bold mb-6">Edit Produk</h1>

            @if ($errors->any())
            <div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4">
                <ul class="list-disc list-inside">
                    @foreach ($errors->all() as $error)
                        <li>{{ $error }}</li>
                    @endforeach
                </ul>
            </div>
            @endif

            <form action="{{ route('products.update', $product) }}" method="POST">
                @csrf
                @method('PUT')

                <div class="mb-4">
                    <label class="block text-gray-700 font-bold mb-2" for="name">
                        Nama Produk
                    </label>
                    <input type="text" 
                           name="name" 
                           id="name" 
                           value="{{ old('name', $product->name) }}"
                           class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline @error('name') border-red-500 @enderror"
                           required>
                    @error('name')
                        <p class="text-red-500 text-xs italic mt-1">{{ $message }}</p>
                    @enderror
                </div>

                <div class="mb-4">
                    <label class="block text-gray-700 font-bold mb-2" for="description">
                        Deskripsi
                    </label>
                    <textarea name="description" 
                              id="description"
                              class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline @error('description') border-red-500 @enderror"
                              rows="4"
                              required>{{ old('description', $product->description) }}</textarea>
                    @error('description')
                        <p class="text-red-500 text-xs italic mt-1">{{ $message }}</p>
                    @enderror
                </div>

                <div class="mb-4">
                    <label class="block text-gray-700 font-bold mb-2" for="price">
                        Harga
                    </label>
                    <input type="number" 
                           name="price" 
                           id="price"
                           value="{{ old('price', $product->price) }}"
                           class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline @error('price') border-red-500 @enderror"
                           step="0.01"
                           required>
                    @error('price')
                        <p class="text-red-500 text-xs italic mt-1">{{ $message }}</p>
                    @enderror
                </div>

                <div class="mb-6">
                    <label class="block text-gray-700 font-bold mb-2" for="stock">
                        Stok
                    </label>
                    <input type="number" 
                           name="stock" 
                           id="stock"
                           value="{{ old('stock', $product->stock) }}"
                           class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline @error('stock') border-red-500 @enderror"
                           required>
                    @error('stock')
                        <p class="text-red-500 text-xs italic mt-1">{{ $message }}</p>
                    @enderror
                </div>

                <div class="flex items-center justify-between">
                    <button type="submit" 
                            class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline">
                        Update Produk
                    </button>
                    <a href="{{ route('products.index') }}" 
                       class="text-gray-600 hover:text-gray-800">
                        Batal
                    </a>
                </div>
            </form>
        </div>
    </div>
</div>
@endsection

Best Practices dan Tips

1. Form Request Validation

  • Pisahkan logika validasi ke Form Request
  • Definisikan pesan error yang informatif
  • Gunakan rules yang sesuai dengan kebutuhan

2. Security

// Di Model Product
protected $guarded = ['id']; // Alternatif dari $fillable

// Di Controller
$product->update($request->only([
    'name',
    'description',
    'price',
    'stock'
]));

3. Optimasi Database

// Di Migration
public function up()
{
    Schema::table('products', function (Blueprint $table) {
        $table->index('name');
        // Tambahkan index untuk kolom yang sering dicari
    });
}

4. Audit Trail

// Di Model Product
use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    protected static function booted()
    {
        static::updated(function ($product) {
            // Log perubahan
            \Log::info('Product updated: ', [
                'id' => $product->id,
                'changes' => $product->getDirty()
            ]);
        });
    }
}

Kesimpulan

Sekarang Anda telah berhasil mengimplementasikan operasi Update dengan:

  • Form edit yang user-friendly
  • Validasi yang kuat
  • Pesan error yang informatif
  • Best practices keamanan

Leave a Reply

Your email address will not be published. Required fields are marked *