CRUD Kriteria dan Alternatif AHP Laravel
Diterbitkan 18 September 2026
Buat Controller
php artisan make:controller KriteriaController --resource
php artisan make:controller AlternatifController --resource
Route
Tambahkan ke grup middleware auth pada routes/web.php:
use App\Http\Controllers\KriteriaController;
use App\Http\Controllers\AlternatifController;
Route::resource('kriteria', KriteriaController::class)->except('show');
Route::resource('alternatif', AlternatifController::class)->except('show');
KriteriaController
app/Http/Controllers/KriteriaController.php:
<?php
namespace App\Http\Controllers;
use App\Models\Kriteria;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
class KriteriaController extends Controller
{
public function index()
{
$items = Kriteria::orderBy('kode')->get();
return view('kriteria.index', compact('items'));
}
public function create()
{
return view('kriteria.form', [
'item' => new Kriteria(),
]);
}
public function store(Request $request)
{
$data = $request->validate([
'kode' => ['required', 'max:10', 'unique:kriteria,kode'],
'nama' => ['required', 'max:255'],
]);
Kriteria::create($data);
return redirect()
->route('kriteria.index')
->with('success', 'Kriteria berhasil ditambahkan.');
}
public function edit(Kriteria $kriterium)
{
return view('kriteria.form', [
'item' => $kriterium,
]);
}
public function update(Request $request, Kriteria $kriterium)
{
$data = $request->validate([
'kode' => [
'required',
'max:10',
Rule::unique('kriteria', 'kode')->ignore($kriterium->id),
],
'nama' => ['required', 'max:255'],
]);
$kriterium->update($data);
return redirect()
->route('kriteria.index')
->with('success', 'Kriteria berhasil diperbarui.');
}
public function destroy(Kriteria $kriterium)
{
$kriterium->delete();
return redirect()
->route('kriteria.index')
->with('success', 'Kriteria berhasil dihapus.');
}
}
View Kriteria
resources/views/kriteria/index.blade.php:
@extends('layouts.app')
@section('title', 'Kriteria')
@section('content')
<div class="d-flex justify-content-between align-items-center mb-3">
<h1 class="h4 mb-0">Kriteria</h1>
<a href="{{ route('kriteria.create') }}" class="btn btn-primary">
Tambah Kriteria
</a>
</div>
<div class="card border-0 shadow-sm">
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered align-middle mb-0">
<thead>
<tr>
<th width="100">Kode</th>
<th>Nama</th>
<th width="160">Aksi</th>
</tr>
</thead>
<tbody>
@forelse($items as $item)
<tr>
<td>{{ $item->kode }}</td>
<td>{{ $item->nama }}</td>
<td>
<a href="{{ route('kriteria.edit', $item) }}"
class="btn btn-warning btn-sm">Edit</a>
<form method="POST"
action="{{ route('kriteria.destroy', $item) }}"
class="d-inline"
onsubmit="return confirm('Hapus data?')">
@csrf
@method('DELETE')
<button class="btn btn-danger btn-sm">Hapus</button>
</form>
</td>
</tr>
@empty
<tr>
<td colspan="3" class="text-center">
Belum ada data.
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
@endsection
resources/views/kriteria/form.blade.php:
@extends('layouts.app')
@section('title', $item->exists ? 'Edit Kriteria' : 'Tambah Kriteria')
@section('content')
<div class="card border-0 shadow-sm">
<div class="card-body">
<h1 class="h4 mb-4">
{{ $item->exists ? 'Edit Kriteria' : 'Tambah Kriteria' }}
</h1>
<form method="POST"
action="{{ $item->exists
? route('kriteria.update', $item)
: route('kriteria.store') }}">
@csrf
@if($item->exists)
@method('PUT')
@endif
<div class="mb-3">
<label class="form-label">Kode</label>
<input type="text" name="kode"
value="{{ old('kode', $item->kode) }}"
class="form-control" required>
</div>
<div class="mb-3">
<label class="form-label">Nama Kriteria</label>
<input type="text" name="nama"
value="{{ old('nama', $item->nama) }}"
class="form-control" required>
</div>
<button class="btn btn-primary">Simpan</button>
<a href="{{ route('kriteria.index') }}"
class="btn btn-secondary">Kembali</a>
</form>
</div>
</div>
@endsection
AlternatifController
app/Http/Controllers/AlternatifController.php:
<?php
namespace App\Http\Controllers;
use App\Models\Alternatif;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
class AlternatifController extends Controller
{
public function index()
{
$items = Alternatif::orderBy('kode')->get();
return view('alternatif.index', compact('items'));
}
public function create()
{
return view('alternatif.form', [
'item' => new Alternatif(),
]);
}
public function store(Request $request)
{
$data = $request->validate([
'kode' => ['required', 'max:10', 'unique:alternatif,kode'],
'nama' => ['required', 'max:255'],
]);
Alternatif::create($data);
return redirect()
->route('alternatif.index')
->with('success', 'Alternatif berhasil ditambahkan.');
}
public function edit(Alternatif $alternatif)
{
return view('alternatif.form', [
'item' => $alternatif,
]);
}
public function update(Request $request, Alternatif $alternatif)
{
$data = $request->validate([
'kode' => [
'required',
'max:10',
Rule::unique('alternatif', 'kode')->ignore($alternatif->id),
],
'nama' => ['required', 'max:255'],
]);
$alternatif->update($data);
return redirect()
->route('alternatif.index')
->with('success', 'Alternatif berhasil diperbarui.');
}
public function destroy(Alternatif $alternatif)
{
$alternatif->delete();
return redirect()
->route('alternatif.index')
->with('success', 'Alternatif berhasil dihapus.');
}
}
View alternatif dapat memakai pola yang sama dengan kriteria.
resources/views/alternatif/index.blade.php:
@extends('layouts.app')
@section('title', 'Alternatif')
@section('content')
<div class="d-flex justify-content-between align-items-center mb-3">
<h1 class="h4 mb-0">Alternatif</h1>
<a href="{{ route('alternatif.create') }}" class="btn btn-primary">
Tambah Alternatif
</a>
</div>
<div class="card border-0 shadow-sm">
<div class="card-body">
<table class="table table-bordered align-middle mb-0">
<thead>
<tr>
<th>Kode</th>
<th>Nama</th>
<th width="160">Aksi</th>
</tr>
</thead>
<tbody>
@forelse($items as $item)
<tr>
<td>{{ $item->kode }}</td>
<td>{{ $item->nama }}</td>
<td>
<a href="{{ route('alternatif.edit', $item) }}"
class="btn btn-warning btn-sm">Edit</a>
<form method="POST"
action="{{ route('alternatif.destroy', $item) }}"
class="d-inline"
onsubmit="return confirm('Hapus data?')">
@csrf
@method('DELETE')
<button class="btn btn-danger btn-sm">Hapus</button>
</form>
</td>
</tr>
@empty
<tr>
<td colspan="3" class="text-center">
Belum ada data.
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
@endsection
resources/views/alternatif/form.blade.php:
@extends('layouts.app')
@section('title', $item->exists ? 'Edit Alternatif' : 'Tambah Alternatif')
@section('content')
<div class="card border-0 shadow-sm">
<div class="card-body">
<h1 class="h4 mb-4">
{{ $item->exists ? 'Edit Alternatif' : 'Tambah Alternatif' }}
</h1>
<form method="POST"
action="{{ $item->exists
? route('alternatif.update', $item)
: route('alternatif.store') }}">
@csrf
@if($item->exists)
@method('PUT')
@endif
<div class="mb-3">
<label class="form-label">Kode</label>
<input type="text" name="kode"
value="{{ old('kode', $item->kode) }}"
class="form-control" required>
</div>
<div class="mb-3">
<label class="form-label">Nama Alternatif</label>
<input type="text" name="nama"
value="{{ old('nama', $item->nama) }}"
class="form-control" required>
</div>
<button class="btn btn-primary">Simpan</button>
<a href="{{ route('alternatif.index') }}"
class="btn btn-secondary">Kembali</a>
</form>
</div>
</div>
@endsection
Tambahkan Menu
Pada navbar layouts/app.blade.php, tambahkan:
<a class="nav-link text-white" href="{{ route('kriteria.index') }}">Kriteria</a>
<a class="nav-link text-white" href="{{ route('alternatif.index') }}">Alternatif</a>
Data Awal
Data awal sudah dibuat melalui AhpSeeder pada bagian sebelumnya.
Kriteria:
C1 - Harga
C2 - Kualitas
C3 - Pelayanan
Alternatif:
A1 - Supplier A
A2 - Supplier B
A3 - Supplier C
Seeder juga sudah membuat seluruh pasangan perbandingan kriteria dan alternatif dengan nilai awal 1.
CRUD pada bagian ini digunakan untuk menambah, mengubah, atau menghapus data kriteria dan alternatif.
Jika jumlah kriteria atau alternatif diubah melalui CRUD, pasangan perbandingan untuk data baru akan diisi pada halaman perbandingan pada langkah berikutnya.


Checkpoint
Pastikan tambah, edit, dan hapus kriteria serta alternatif berjalan normal.




