Tutorial

Perbandingan Alternatif pada Setiap Kriteria AHP Laravel

Membuat perbandingan berpasangan alternatif untuk setiap kriteria dan menghitung bobot prioritas alternatif pada aplikasi AHP Laravel.

Daftar Isi

Buat Controller

php artisan make:controller PerbandinganAlternatifController

app/Http/Controllers/PerbandinganAlternatifController.php:

<?php

namespace App\Http\Controllers;

use App\Models\Alternatif;
use App\Models\Kriteria;
use App\Models\PerbandinganAlternatif;
use App\Services\AhpService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;

class PerbandinganAlternatifController extends Controller
{
    private array $skalaAhp = [
        '0.111111',
        '0.125',
        '0.142857',
        '0.166667',
        '0.2',
        '0.25',
        '0.333333',
        '0.5',
        '1',
        '2',
        '3',
        '4',
        '5',
        '6',
        '7',
        '8',
        '9',
    ];

    public function redirectToFirst()
    {
        $kriteria = Kriteria::orderBy('kode')->first();

        if (! $kriteria) {
            return redirect()
                ->route('kriteria.index')
                ->withErrors('Tambahkan kriteria terlebih dahulu.');
        }

        return redirect()
            ->route('perbandingan-alternatif.index', $kriteria);
    }

    public function index(Kriteria $kriteria, AhpService $ahp)
    {
        $alternatif = Alternatif::orderBy('kode')->get();

        $records = PerbandinganAlternatif::where(
            'kriteria_id',
            $kriteria->id
        )->get();

        $ids = $alternatif->pluck('id')->all();

        $matrix = $ids
            ? $ahp->matrix(
                $ids,
                $records,
                'alternatif_1_id',
                'alternatif_2_id'
            )
            : [];

        $hasil = count($ids) >= 2
            ? $ahp->priority($matrix, $ids)
            : null;

        $konsistensi = $hasil
            ? $ahp->consistency($matrix, $hasil['weights'], $ids)
            : null;

        $semuaKriteria = Kriteria::orderBy('kode')->get();

        return view('perbandingan-alternatif.index', compact(
            'kriteria',
            'semuaKriteria',
            'alternatif',
            'matrix',
            'hasil',
            'konsistensi'
        ));
    }

    public function store(Request $request, Kriteria $kriteria)
    {
        $alternatif = Alternatif::orderBy('kode')->get();
        $ids = $alternatif->pluck('id')->all();

        $request->validate([
            'nilai' => ['required', 'array'],
            'nilai.*.*' => [
                'required',
                Rule::in($this->skalaAhp),
            ],
        ]);

        DB::transaction(function () use ($request, $kriteria, $ids) {
            PerbandinganAlternatif::where(
                'kriteria_id',
                $kriteria->id
            )->delete();

            for ($i = 0; $i < count($ids); $i++) {
                for ($j = $i + 1; $j < count($ids); $j++) {
                    $a = $ids[$i];
                    $b = $ids[$j];

                    PerbandinganAlternatif::create([
                        'kriteria_id' => $kriteria->id,
                        'alternatif_1_id' => $a,
                        'alternatif_2_id' => $b,
                        'nilai' => (float) $request->input("nilai.$a.$b"),
                    ]);
                }
            }

            Alternatif::query()->update([
                'nilai_akhir' => null,
                'ranking' => null,
            ]);
        });

        return redirect()
            ->route('perbandingan-alternatif.index', $kriteria)
            ->with('success', 'Perbandingan alternatif berhasil disimpan.');
    }
}

Route

Tambahkan pada grup auth:

use App\Http\Controllers\PerbandinganAlternatifController;

Route::get(
    '/perbandingan-alternatif',
    [PerbandinganAlternatifController::class, 'redirectToFirst']
)->name('perbandingan-alternatif.first');

Route::get(
    '/perbandingan-alternatif/{kriteria}',
    [PerbandinganAlternatifController::class, 'index']
)->name('perbandingan-alternatif.index');

Route::post(
    '/perbandingan-alternatif/{kriteria}',
    [PerbandinganAlternatifController::class, 'store']
)->name('perbandingan-alternatif.store');

Tambahkan Menu Perbandingan Alternatif

Pada resources/views/layouts/app.blade.php, tambahkan:

<a class="nav-link text-white"
   href="{{ route('perbandingan-alternatif.first') }}">
    Perbandingan Alternatif
</a>

Route tersebut akan mengarahkan pengguna ke kriteria pertama melalui controller, sehingga layout tidak melakukan query database langsung.

View

Buat resources/views/perbandingan-alternatif/index.blade.php:

@extends('layouts.app')

@section('title', 'Perbandingan Alternatif')

@section('content')
<h1 class="h4 mb-3">Perbandingan Alternatif</h1>

<div class="mb-3">
    <label class="form-label">Pilih Kriteria</label>
    <select class="form-select"
            onchange="if(this.value) window.location=this.value">
        @foreach($semuaKriteria as $item)
            <option
                value="{{ route('perbandingan-alternatif.index', $item) }}"
                @selected($item->id === $kriteria->id)>
                {{ $item->kode }} - {{ $item->nama }}
            </option>
        @endforeach
    </select>
</div>

<div class="alert alert-info">
    Kriteria aktif:
    <strong>{{ $kriteria->kode }} - {{ $kriteria->nama }}</strong>
</div>

@php
    $skalaAhp = [
        '0.111111' => '1/9',
        '0.125' => '1/8',
        '0.142857' => '1/7',
        '0.166667' => '1/6',
        '0.2' => '1/5',
        '0.25' => '1/4',
        '0.333333' => '1/3',
        '0.5' => '1/2',
        '1' => '1',
        '2' => '2',
        '3' => '3',
        '4' => '4',
        '5' => '5',
        '6' => '6',
        '7' => '7',
        '8' => '8',
        '9' => '9',
    ];
@endphp

<form method="POST"
      action="{{ route('perbandingan-alternatif.store', $kriteria) }}">
    @csrf

    <div class="card border-0 shadow-sm mb-4">
        <div class="card-body table-responsive">
            <table class="table table-bordered text-center align-middle">
                <thead>
                    <tr>
                        <th>Alternatif</th>
                        @foreach($alternatif as $kolom)
                            <th>{{ $kolom->kode }}</th>
                        @endforeach
                    </tr>
                </thead>
                <tbody>
                    @foreach($alternatif as $i => $baris)
                        <tr>
                            <th>{{ $baris->kode }}</th>

                            @foreach($alternatif as $j => $kolom)
                                <td>
                                    @if($i === $j)
                                        1
                                    @elseif($i < $j)
                                        @php
                                            $nilaiAktif = old(
                                                "nilai.{$baris->id}.{$kolom->id}",
                                                $matrix[$baris->id][$kolom->id] ?? 1
                                            );
                                        @endphp

                                        <select
                                            name="nilai[{{ $baris->id }}][{{ $kolom->id }}]"
                                            class="form-select"
                                            required>
                                            @foreach($skalaAhp as $value => $label)
                                                <option
                                                    value="{{ $value }}"
                                                    @selected(abs((float) $nilaiAktif - (float) $value) < 0.000001)>
                                                    {{ $label }}
                                                </option>
                                            @endforeach
                                        </select>
                                    @else
                                        {{ number_format(
                                            $matrix[$baris->id][$kolom->id] ?? 1,
                                            4
                                        ) }}
                                    @endif
                                </td>
                            @endforeach
                        </tr>
                    @endforeach
                </tbody>
            </table>

            <button class="btn btn-primary">
                Simpan dan Hitung
            </button>
        </div>
    </div>
</form>

@if($hasil)
<div class="card border-0 shadow-sm">
    <div class="card-body">
        <h2 class="h5">Bobot Alternatif</h2>

        <table class="table table-bordered">
            <thead>
                <tr>
                    <th>Alternatif</th>
                    <th>Bobot</th>
                </tr>
            </thead>
            <tbody>
                @foreach($alternatif as $item)
                    <tr>
                        <td>{{ $item->kode }} - {{ $item->nama }}</td>
                        <td>
                            {{ number_format(
                                $hasil['weights'][$item->id],
                                6
                            ) }}
                        </td>
                    </tr>
                @endforeach
            </tbody>
        </table>

        <p>
            CR:
            <strong>
                {{ number_format($konsistensi['cr'], 6) }}
            </strong>
        </p>

        @if($konsistensi['cr'] <= 0.1)
            <div class="alert alert-success mb-0">
                Matriks konsisten.
            </div>
        @else
            <div class="alert alert-danger mb-0">
                Matriks belum konsisten.
            </div>
        @endif
    </div>
</div>
@endif
@endsection

Cara Input

Lakukan perbandingan alternatif untuk setiap kriteria.

Contoh:

Kriteria C1 - Harga
A1 vs A2
A1 vs A3
A2 vs A3

Nilai dipilih melalui dropdown skala AHP:

1/9, 1/8, 1/7, 1/6, 1/5, 1/4, 1/3, 1/2,
1,
2, 3, 4, 5, 6, 7, 8, 9

Setiap matriks sebaiknya memiliki CR ≤ 0,1.

Tutorial AHP Laravel Perbandingan Alternatif

Checkpoint

Pastikan:

  • Input menggunakan dropdown skala AHP.
  • Nilai pecahan seperti 1/3 dapat dipilih langsung.
  • Nilai kebalikan dihitung otomatis.
  • Semua kriteria memiliki perbandingan alternatif.
  • CR setiap matriks ≤ 0,1.
Lanjut: Perhitungan Nilai Akhir dan Ranking AHP

Tulis Komentar

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *