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
Tutorial Saw Laravel Login
Tutorial Saw Laravel Dashboard

Checkpoint

Pastikan:

  • migration berhasil;
  • seeder berhasil;
  • login berhasil;
  • logout berhasil;
  • dashboard tampil;
  • project berjalan melalui php artisan serve.

Lanjut: CRUD Kriteria dan Alternatif SAW