Bagian 4 dari seri
Perhitungan SAW Laravel: Normalisasi dan Nilai Preferensi
Diterbitkan 21 September 2026
Pada bagian ini buat SawService. Salin kode berikut apa adanya.
Buat Folder Service
Buat folder:
app/Services
Lalu buat:
app/Services/SawService.php
SawService
<?php
namespace App\Services;
use InvalidArgumentException;
class SawService
{
public function calculate(
array $matrix,
array $weights,
array $attributes
): array {
if (empty($matrix)) {
throw new InvalidArgumentException(
'Matriks keputusan tidak boleh kosong.'
);
}
$alternativeIds = array_keys($matrix);
$criteriaIds = array_keys(reset($matrix));
$normalizedWeights = $this->normalizeWeights(
$weights,
$criteriaIds
);
$normalized = $this->normalizeMatrix(
$matrix,
$attributes,
$alternativeIds,
$criteriaIds
);
$preferences = $this->preferences(
$normalized,
$normalizedWeights,
$alternativeIds,
$criteriaIds
);
return [
'weights' => $normalizedWeights,
'normalized' => $normalized,
'preferences' => $preferences,
];
}
public function normalizeWeights(
array $weights,
array $criteriaIds
): array {
$total = 0.0;
foreach ($criteriaIds as $criteriaId) {
$weight = (float) ($weights[$criteriaId] ?? 0);
if ($weight <= 0) {
throw new InvalidArgumentException(
'Semua bobot kriteria harus lebih besar dari 0.'
);
}
$total += $weight;
}
$result = [];
foreach ($criteriaIds as $criteriaId) {
$result[$criteriaId] =
(float) $weights[$criteriaId] / $total;
}
return $result;
}
public function normalizeMatrix(
array $matrix,
array $attributes,
array $alternativeIds,
array $criteriaIds
): array {
$normalized = [];
foreach ($criteriaIds as $criteriaId) {
$values = [];
foreach ($alternativeIds as $alternativeId) {
$values[] =
(float) $matrix[$alternativeId][$criteriaId];
}
$attribute =
$attributes[$criteriaId] ?? null;
if ($attribute === 'benefit') {
$maxValue = max($values);
if ($maxValue == 0.0) {
throw new InvalidArgumentException(
"Nilai maksimum kriteria ID {$criteriaId} adalah 0."
);
}
foreach ($alternativeIds as $alternativeId) {
$normalized[$alternativeId][$criteriaId] =
(float) $matrix[$alternativeId][$criteriaId]
/ $maxValue;
}
} elseif ($attribute === 'cost') {
$minValue = min($values);
if ($minValue <= 0.0) {
throw new InvalidArgumentException(
"Nilai minimum kriteria cost ID {$criteriaId} harus lebih besar dari 0."
);
}
foreach ($alternativeIds as $alternativeId) {
$value =
(float) $matrix[$alternativeId][$criteriaId];
if ($value <= 0.0) {
throw new InvalidArgumentException(
"Nilai kriteria cost ID {$criteriaId} harus lebih besar dari 0."
);
}
$normalized[$alternativeId][$criteriaId] =
$minValue / $value;
}
} else {
throw new InvalidArgumentException(
"Atribut kriteria ID {$criteriaId} tidak valid."
);
}
}
return $normalized;
}
public function preferences(
array $normalized,
array $weights,
array $alternativeIds,
array $criteriaIds
): array {
$preferences = [];
foreach ($alternativeIds as $alternativeId) {
$score = 0.0;
foreach ($criteriaIds as $criteriaId) {
$score +=
$normalized[$alternativeId][$criteriaId]
* $weights[$criteriaId];
}
$preferences[$alternativeId] = $score;
}
return $preferences;
}
}
Urutan Perhitungan
Service menjalankan:
1. Normalisasi bobot
2. Normalisasi matriks
3. Perhitungan nilai preferensi
Aturan normalisasi:
benefit:
r = nilai / nilai maksimum
cost:
r = nilai minimum / nilai
Nilai preferensi:
V = Σ (bobot × nilai normalisasi)
Nilai preferensi terbesar mendapat ranking tertinggi.
Data Detail yang Dihasilkan Service
weights
normalized
preferences
Data tersebut dipakai pada halaman hasil.
Menyiapkan Matriks dari Database
$kriteria = Kriteria::orderBy('kode')->get();
$alternatif = Alternatif::orderBy('kode')->get();
$penilaian = Penilaian::all();
$matrix = [];
$weights = [];
$attributes = [];
foreach ($kriteria as $itemKriteria) {
$weights[$itemKriteria->id] =
(float) $itemKriteria->bobot;
$attributes[$itemKriteria->id] =
$itemKriteria->atribut;
}
$nilaiMap = $penilaian->keyBy(function ($item) {
return $item->alternatif_id
. '-'
. $item->kriteria_id;
});
foreach ($alternatif as $itemAlternatif) {
foreach ($kriteria as $itemKriteria) {
$key =
$itemAlternatif->id
. '-'
. $itemKriteria->id;
$matrix[$itemAlternatif->id][$itemKriteria->id] =
(float) $nilaiMap[$key]->nilai;
}
}
Memanggil Service
$hasil = $saw->calculate(
$matrix,
$weights,
$attributes
);
Hasil:
[
'weights' => ...,
'normalized' => ...,
'preferences' => ...,
]
Checkpoint
Pastikan:
- bobot dinormalisasi;
- atribut benefit dan cost dihitung berbeda;
- matriks normalisasi terbentuk;
- nilai preferensi dihitung;
- nilai terbesar menjadi ranking tertinggi.




