Bagian 1 dari seri
Persiapan Project SAW Laravel, Bootstrap, Login, dan Database
Diterbitkan 21 September 2026
Ikuti langkah berikut secara berurutan. Setelah selesai, project harus bisa login dan menampilkan dashboard.
Buat Project Laravel
composer create-project laravel/laravel saw-laravel
cd saw-laravel
php artisan key:generate
Konfigurasi Database
Buat database:
saw_laravel
Atur .env:
APP_NAME="SAW Laravel"
APP_URL=http://127.0.0.1:8000
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=saw_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 Penilaian -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->decimal('bobot', 12, 6);
$table->enum('atribut', ['benefit', 'cost']);
$table->timestamps();
});
Migration Alternatif
Schema::create('alternatif', function (Blueprint $table) {
$table->id();
$table->string('kode', 10)->unique();
$table->string('nama');
$table->decimal('nilai_preferensi', 14, 10)->nullable();
$table->unsignedInteger('ranking')->nullable();
$table->timestamps();
});
Migration Penilaian
Schema::create('penilaian', function (Blueprint $table) {
$table->id();
$table->foreignId('alternatif_id')
->constrained('alternatif')
->cascadeOnDelete();
$table->foreignId('kriteria_id')
->constrained('kriteria')
->cascadeOnDelete();
$table->decimal('nilai', 14, 6);
$table->timestamps();
$table->unique(
['alternatif_id', 'kriteria_id'],
'penilaian_alternatif_kriteria_unique'
);
});
Model Kriteria
app/Models/Kriteria.php:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Kriteria extends Model
{
protected $table = 'kriteria';
protected $fillable = [
'kode',
'nama',
'bobot',
'atribut',
];
protected $casts = [
'bobot' => 'float',
];
public function penilaian()
{
return $this->hasMany(Penilaian::class);
}
}
Model Alternatif
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_preferensi',
'ranking',
];
protected $casts = [
'nilai_preferensi' => 'float',
];
public function penilaian()
{
return $this->hasMany(Penilaian::class);
}
}
Model Penilaian
app/Models/Penilaian.php:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Penilaian extends Model
{
protected $table = 'penilaian';
protected $fillable = [
'alternatif_id',
'kriteria_id',
'nilai',
];
protected $casts = [
'nilai' => 'float',
];
public function alternatif()
{
return $this->belongsTo(Alternatif::class);
}
public function kriteria()
{
return $this->belongsTo(Kriteria::class);
}
}
Buat Seeder
php artisan make:seeder SawSeeder
database/seeders/SawSeeder.php:
<?php
namespace Database\Seeders;
use App\Models\Alternatif;
use App\Models\Kriteria;
use App\Models\Penilaian;
use App\Models\User;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;
class SawSeeder extends Seeder
{
public function run(): void
{
User::updateOrCreate(
['email' => 'admin@example.com'],
[
'name' => 'Administrator',
'password' => Hash::make('admin12345'),
]
);
$dataKriteria = [
[
'kode' => 'C1',
'nama' => 'Harga',
'bobot' => 30,
'atribut' => 'cost',
],
[
'kode' => 'C2',
'nama' => 'Kualitas',
'bobot' => 40,
'atribut' => 'benefit',
],
[
'kode' => 'C3',
'nama' => 'Pelayanan',
'bobot' => 30,
'atribut' => 'benefit',
],
];
foreach ($dataKriteria as $item) {
Kriteria::updateOrCreate(
['kode' => $item['kode']],
$item
);
}
$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_preferensi' => null,
'ranking' => null,
]
);
}
$nilaiAwal = [
'A1' => ['C1' => 80, 'C2' => 8, 'C3' => 9],
'A2' => ['C1' => 70, 'C2' => 9, 'C3' => 8],
'A3' => ['C1' => 75, 'C2' => 7, 'C3' => 9],
];
$kriteria = Kriteria::all()->keyBy('kode');
$alternatif = Alternatif::all()->keyBy('kode');
foreach ($nilaiAwal as $kodeAlternatif => $nilaiKriteria) {
foreach ($nilaiKriteria as $kodeKriteria => $nilai) {
Penilaian::updateOrCreate(
[
'alternatif_id' => $alternatif[$kodeAlternatif]->id,
'kriteria_id' => $kriteria[$kodeKriteria]->id,
],
[
'nilai' => $nilai,
]
);
}
}
}
}
Daftarkan pada database/seeders/DatabaseSeeder.php:
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
public function run(): void
{
$this->call(SawSeeder::class);
}
}
Jalankan:
php artisan migrate:fresh --seed
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(route('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');
}
}
DashboardController
app/Http/Controllers/DashboardController.php:
<?php
namespace App\Http\Controllers;
class DashboardController extends Controller
{
public function index()
{
return view('dashboard');
}
}
Route Dasar
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');
});
Layout Bootstrap
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', 'SAW 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') }}">
SAW 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 SAW 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">
<h2 class="h4 mb-4">Login SAW Laravel</h2>
<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">
<h2 class="h4">Dashboard SAW</h2>
<p class="mb-0">
Project Laravel dan autentikasi berhasil dibuat.
</p>
</div>
</div>
@endsection
Menjalankan Project
Pastikan MySQL sudah aktif.
Jalankan:
php artisan serve
Buka:
http://127.0.0.1:8000
Halaman login:
http://127.0.0.1:8000/login


Checkpoint
Pastikan:
- migration berhasil;
- seeder berhasil;
- login berhasil;
- logout berhasil;
- dashboard tampil;
- project berjalan melalui
php artisan serve.




