Bagian 3 dari seri
Input Nilai Alternatif pada Setiap Kriteria TOPSIS Laravel
Diterbitkan 21 September 2026
Pada bagian ini buat form untuk mengisi nilai setiap alternatif pada setiap kriteria.
Contoh Matriks Keputusan
Misalnya tersedia:
C1 - Harga
C2 - Kualitas
C3 - Pelayanan
dan:
A1 - Supplier A
A2 - Supplier B
A3 - Supplier C
Matriks keputusan:
| Alternatif | C1 | C2 | C3 |
|---|---|---|---|
| A1 | 80 | 8 | 9 |
| A2 | 70 | 9 | 8 |
| A3 | 75 | 7 | 9 |
Setiap sel disimpan pada tabel penilaian.
Buat Controller
php artisan make:controller PenilaianController
PenilaianController
app/Http/Controllers/PenilaianController.php:
<?php
namespace App\Http\Controllers;
use App\Models\Alternatif;
use App\Models\Kriteria;
use App\Models\Penilaian;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class PenilaianController extends Controller
{
public function index()
{
$kriteria = Kriteria::orderBy('kode')->get();
$alternatif = Alternatif::orderBy('kode')->get();
$records = Penilaian::all()
->keyBy(function ($item) {
return $item->alternatif_id
. '-'
. $item->kriteria_id;
});
return view('penilaian.index', compact(
'kriteria',
'alternatif',
'records'
));
}
public function store(Request $request)
{
$kriteria = Kriteria::orderBy('kode')->get();
$alternatif = Alternatif::orderBy('kode')->get();
if ($kriteria->isEmpty() || $alternatif->isEmpty()) {
return back()->withErrors(
'Kriteria dan alternatif harus tersedia.'
);
}
$request->validate([
'nilai' => ['required', 'array'],
'nilai.*' => ['required', 'array'],
'nilai.*.*' => [
'required',
'numeric',
'gte:0',
],
]);
DB::transaction(function () use (
$request,
$kriteria,
$alternatif
) {
foreach ($alternatif as $itemAlternatif) {
foreach ($kriteria as $itemKriteria) {
$nilai = $request->input(
"nilai.{$itemAlternatif->id}.{$itemKriteria->id}"
);
Penilaian::updateOrCreate(
[
'alternatif_id' => $itemAlternatif->id,
'kriteria_id' => $itemKriteria->id,
],
[
'nilai' => (float) $nilai,
]
);
}
}
Alternatif::query()->update([
'nilai_preferensi' => null,
'ranking' => null,
]);
});
return redirect()
->route('penilaian.index')
->with(
'success',
'Nilai alternatif berhasil disimpan.'
);
}
}
Route
Tambahkan pada grup auth:
use App\Http\Controllers\PenilaianController;
Route::get(
'/penilaian',
[PenilaianController::class, 'index']
)->name('penilaian.index');
Route::post(
'/penilaian',
[PenilaianController::class, 'store']
)->name('penilaian.store');
Tambahkan Menu Penilaian
Pada navbar:
<a
class="nav-link text-white"
href="{{ route('penilaian.index') }}">
Penilaian
</a>
Buat View Matriks Penilaian
Buat:
resources/views/penilaian/index.blade.php
Isi:
@extends('layouts.app')
@section('title', 'Penilaian')
@section('content')
<div class="d-flex justify-content-between align-items-center mb-3">
<div>
<h1 class="h4 mb-1">Penilaian Alternatif</h1>
<p class="text-muted mb-0">
Masukkan nilai setiap alternatif pada setiap kriteria.
</p>
</div>
</div>
@if($kriteria->isEmpty())
<div class="alert alert-warning">
Belum ada kriteria.
</div>
@elseif($alternatif->isEmpty())
<div class="alert alert-warning">
Belum ada alternatif.
</div>
@else
<form
method="POST"
action="{{ route('penilaian.store') }}">
@csrf
<div class="card border-0 shadow-sm">
<div class="card-body">
<div class="table-responsive">
<table
class="table table-bordered align-middle text-center">
<thead>
<tr>
<th class="text-start">Alternatif</th>
@foreach($kriteria as $itemKriteria)
<th>
{{ $itemKriteria->kode }}
<div class="small fw-normal">
{{ $itemKriteria->nama }}
</div>
<div class="small fw-normal text-muted">
{{ ucfirst($itemKriteria->atribut) }}
|
Bobot: {{ $itemKriteria->bobot }}
</div>
</th>
@endforeach
</tr>
</thead>
<tbody>
@foreach($alternatif as $itemAlternatif)
<tr>
<th class="text-start">
{{ $itemAlternatif->kode }}
-
{{ $itemAlternatif->nama }}
</th>
@foreach($kriteria as $itemKriteria)
@php
$key =
$itemAlternatif->id
. '-'
. $itemKriteria->id;
$record =
$records->get($key);
$nilaiLama = old(
"nilai.{$itemAlternatif->id}.{$itemKriteria->id}",
$record?->nilai
);
@endphp
<td style="min-width:150px">
<input
type="number"
name="nilai[{{ $itemAlternatif->id }}][{{ $itemKriteria->id }}]"
value="{{ $nilaiLama }}"
class="form-control text-end"
step="0.000001"
min="0"
required>
</td>
@endforeach
</tr>
@endforeach
</tbody>
</table>
</div>
<button class="btn btn-primary">
Simpan Penilaian
</button>
</div>
</div>
</form>
@endif
@endsection
Contoh Data Tutorial
Masukkan:
A1:
C1 = 80
C2 = 8
C3 = 9
A2:
C1 = 70
C2 = 9
C3 = 8
A3:
C1 = 75
C2 = 7
C3 = 9
Dengan kriteria:
C1 = Harga | Cost | Bobot 30
C2 = Kualitas | Benefit | Bobot 40
C3 = Pelayanan | Benefit | Bobot 30
Data ini digunakan pada bagian berikutnya untuk melihat proses normalisasi dan ranking.

Checkpoint
Pastikan:
- seluruh alternatif muncul sebagai baris;
- seluruh kriteria muncul sebagai kolom;
- atribut dan bobot kriteria terlihat;
- nilai dapat disimpan;
- nilai lama tampil kembali saat halaman dibuka;
- kombinasi alternatif-kriteria tidak terduplikasi;
- hasil ranking lama dikosongkan setelah nilai berubah;
- nilai negatif ditolak;
- semua sel wajib diisi.




