Persiapan Project AHP Laravel, Bootstrap, Login, dan Database
Diterbitkan 18 September 2026
Buat Project Laravel
composer create-project laravel/laravel ahp-laravel
cd ahp-laravel
php artisan key:generate
Atur .env:
APP_NAME="AHP Laravel"
APP_URL=http://localhost/ahp-laravel/public
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=ahp_laravel
DB_USERNAME=root
DB_PASSWORD=
Buat Model dan Migration
php artisan make:model Kriteria -m
php artisan make:model Alternatif -m
php artisan make:model PerbandinganKriteria -m
php artisan make:model PerbandinganAlternatif -m
php artisan make:controller AuthController
php artisan make:controller DashboardController
Migration kriteria:
Schema::create('kriteria', function (Blueprint $table) {
$table->id();
$table->string('kode', 10)->unique();
$table->string('nama');
$table->timestamps();
});
Migration alternatif:
Schema::create('alternatif', function (Blueprint $table) {
$table->id();
$table->string('kode', 10)->unique();
$table->string('nama');
$table->decimal('nilai_akhir', 12, 8)->nullable();
$table->unsignedInteger('ranking')->nullable();
$table->timestamps();
});
Migration perbandingan_kriteria:
Schema::create('perbandingan_kriteria', function (Blueprint $table) {
$table->id();
$table->foreignId('kriteria_1_id')->constrained('kriteria')->cascadeOnDelete();
$table->foreignId('kriteria_2_id')->constrained('kriteria')->cascadeOnDelete();
$table->decimal('nilai', 12, 6);
$table->timestamps();
$table->unique(['kriteria_1_id', 'kriteria_2_id']);
});
Migration perbandingan_alternatif:
Schema::create('perbandingan_alternatif', function (Blueprint $table) {
$table->id();
$table->foreignId('kriteria_id')->constrained('kriteria')->cascadeOnDelete();
$table->foreignId('alternatif_1_id')->constrained('alternatif')->cascadeOnDelete();
$table->foreignId('alternatif_2_id')->constrained('alternatif')->cascadeOnDelete();
$table->decimal('nilai', 12, 6);
$table->timestamps();
$table->unique(['kriteria_id', 'alternatif_1_id', 'alternatif_2_id']);
});
Jalankan:
php artisan migrate
Model
app/Models/Kriteria.php:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Kriteria extends Model
{
protected $table = 'kriteria';
protected $fillable = ['kode', 'nama'];
}
app/Models/Alternatif.php:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Alternatif extends Model
{
protected $table = 'alternatif';
protected $fillable = [
'kode', 'nama', 'nilai_akhir', 'ranking'
];
}
app/Models/PerbandinganKriteria.php:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class PerbandinganKriteria extends Model
{
protected $table = 'perbandingan_kriteria';
protected $fillable = [
'kriteria_1_id', 'kriteria_2_id', 'nilai'
];
}
app/Models/PerbandinganAlternatif.php:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class PerbandinganAlternatif extends Model
{
protected $table = 'perbandingan_alternatif';
protected $fillable = [
'kriteria_id', 'alternatif_1_id', 'alternatif_2_id', 'nilai'
];
}
Seeder Data Awal
Buat satu seeder untuk seluruh data awal aplikasi:
php artisan make:seeder AhpSeeder
Buka database/seeders/AhpSeeder.php:
<?php
namespace Database\Seeders;
use App\Models\Alternatif;
use App\Models\Kriteria;
use App\Models\PerbandinganAlternatif;
use App\Models\PerbandinganKriteria;
use App\Models\User;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;
class AhpSeeder extends Seeder
{
public function run(): void
{
User::updateOrCreate(
['email' => 'admin@example.com'],
[
'name' => 'Administrator',
'password' => Hash::make('admin12345'),
]
);
$dataKriteria = [
['kode' => 'C1', 'nama' => 'Harga'],
['kode' => 'C2', 'nama' => 'Kualitas'],
['kode' => 'C3', 'nama' => 'Pelayanan'],
];
foreach ($dataKriteria as $item) {
Kriteria::updateOrCreate(
['kode' => $item['kode']],
['nama' => $item['nama']]
);
}
$dataAlternatif = [
['kode' => 'A1', 'nama' => 'Supplier A'],
['kode' => 'A2', 'nama' => 'Supplier B'],
['kode' => 'A3', 'nama' => 'Supplier C'],
];
foreach ($dataAlternatif as $item) {
Alternatif::updateOrCreate(
['kode' => $item['kode']],
[
'nama' => $item['nama'],
'nilai_akhir' => null,
'ranking' => null,
]
);
}
$kriteria = Kriteria::orderBy('kode')->get();
$alternatif = Alternatif::orderBy('kode')->get();
// Nilai awal perbandingan kriteria = 1
for ($i = 0; $i < $kriteria->count(); $i++) {
for ($j = $i + 1; $j < $kriteria->count(); $j++) {
PerbandinganKriteria::updateOrCreate(
[
'kriteria_1_id' => $kriteria[$i]->id,
'kriteria_2_id' => $kriteria[$j]->id,
],
[
'nilai' => 1,
]
);
}
}
// Nilai awal perbandingan alternatif pada setiap kriteria = 1
foreach ($kriteria as $itemKriteria) {
for ($i = 0; $i < $alternatif->count(); $i++) {
for ($j = $i + 1; $j < $alternatif->count(); $j++) {
PerbandinganAlternatif::updateOrCreate(
[
'kriteria_id' => $itemKriteria->id,
'alternatif_1_id' => $alternatif[$i]->id,
'alternatif_2_id' => $alternatif[$j]->id,
],
[
'nilai' => 1,
]
);
}
}
}
}
}
Daftarkan pada database/seeders/DatabaseSeeder.php:
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
public function run(): void
{
$this->call(AhpSeeder::class);
}
}
Jalankan migration sekaligus seeder:
php artisan migrate:fresh --seed
Data awal yang tersedia:
User
admin@example.com
Password: admin12345
Kriteria
C1 - Harga
C2 - Kualitas
C3 - Pelayanan
Alternatif
A1 - Supplier A
A2 - Supplier B
A3 - Supplier C
Seeder juga membuat seluruh pasangan perbandingan dengan nilai awal 1.
Contoh perbandingan kriteria:
C1 vs C2 = 1
C1 vs C3 = 1
C2 vs C3 = 1
Pada setiap kriteria, pasangan alternatif juga dibuat dengan nilai awal 1.
Nilai 1 berarti kedua elemen dianggap sama penting. Nilai tersebut nantinya dapat diubah melalui form perbandingan pada aplikasi.
AuthController
app/Http/Controllers/AuthController.php:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class AuthController extends Controller
{
public function create()
{
return view('auth.login');
}
public function store(Request $request)
{
$credentials = $request->validate([
'email' => ['required', 'email'],
'password' => ['required'],
]);
if (Auth::attempt($credentials, $request->boolean('remember'))) {
$request->session()->regenerate();
return redirect()->intended('/dashboard');
}
return back()->withErrors([
'email' => 'Email atau password salah.',
])->onlyInput('email');
}
public function destroy(Request $request)
{
Auth::logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect()->route('login');
}
}
Route
routes/web.php:
<?php
use App\Http\Controllers\AuthController;
use App\Http\Controllers\DashboardController;
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
return redirect()->route('dashboard');
});
Route::middleware('guest')->group(function () {
Route::get('/login', [AuthController::class, 'create'])->name('login');
Route::post('/login', [AuthController::class, 'store'])
->middleware('throttle:5,1')
->name('login.store');
});
Route::middleware('auth')->group(function () {
Route::get('/dashboard', [DashboardController::class, 'index'])
->name('dashboard');
Route::post('/logout', [AuthController::class, 'destroy'])
->name('logout');
});
app/Http/Controllers/DashboardController.php:
<?php
namespace App\Http\Controllers;
class DashboardController extends Controller
{
public function index()
{
return view('dashboard');
}
}
Layout Bootstrap
Buat resources/views/layouts/app.blade.php:
<!doctype html>
<html lang="id">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>@yield('title', 'AHP Laravel')</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body class="bg-light">
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<div class="container">
<a class="navbar-brand fw-bold" href="{{ route('dashboard') }}">
AHP Laravel
</a>
@auth
<div class="d-flex align-items-center gap-3 text-white">
<span>{{ auth()->user()->name }}</span>
<form method="POST" action="{{ route('logout') }}">
@csrf
<button class="btn btn-outline-light btn-sm">Logout</button>
</form>
</div>
@endauth
</div>
</nav>
<main class="container py-4">
@if(session('success'))
<div class="alert alert-success">{{ session('success') }}</div>
@endif
@if($errors->any())
<div class="alert alert-danger">
<ul class="mb-0">
@foreach($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
@yield('content')
</main>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
Halaman Login
resources/views/auth/login.blade.php:
<!doctype html>
<html lang="id">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Login AHP Laravel</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body class="bg-light">
<div class="container min-vh-100 d-flex align-items-center justify-content-center">
<div class="card border-0 shadow-sm" style="width:100%;max-width:420px">
<div class="card-body p-4">
<h1 class="h4 mb-4">Login AHP Laravel</h1>
<form method="POST" action="{{ route('login.store') }}">
@csrf
<div class="mb-3">
<label class="form-label">Email</label>
<input type="email" name="email"
value="{{ old('email') }}"
class="form-control" required autofocus>
</div>
<div class="mb-3">
<label class="form-label">Password</label>
<input type="password" name="password"
class="form-control" required>
</div>
<div class="form-check mb-3">
<input class="form-check-input"
type="checkbox"
name="remember"
value="1"
id="remember">
<label class="form-check-label" for="remember">
Ingat saya
</label>
</div>
<button class="btn btn-primary w-100">Login</button>
</form>
</div>
</div>
</div>
</body>
</html>
Dashboard
resources/views/dashboard.blade.php:
@extends('layouts.app')
@section('title', 'Dashboard')
@section('content')
<div class="card border-0 shadow-sm">
<div class="card-body">
<h1 class="h4">Dashboard AHP</h1>
<p class="mb-0">
Project Laravel dan autentikasi berhasil dibuat.
</p>
</div>
</div>
@endsection
Karena project dijalankan melalui XAMPP, simpan project di folder htdocs dan akses melalui:
http://localhost/ahp-laravel/public/
Halaman login:
http://localhost/ahp-laravel/public/login
Jika sebelumnya konfigurasi route atau .env sudah pernah di-cache, jalankan:
php artisan optimize:clear


Checkpoint
Pastikan:
- Login berhasil.
- Pengunjung yang belum login diarahkan ke halaman login.
- Logout berhasil.
- Semua migration berhasil.
- Bootstrap tampil normal.




