Backend (Laravel)
Pendahuluan
Backend aplikasi Absensi GPS dibangun menggunakan framework Laravel 12, yang menyediakan struktur yang kuat dan fitur-fitur modern untuk pengembangan aplikasi web. Backend bertanggung jawab untuk mengelola data, autentikasi pengguna, dan menyediakan API untuk frontend dan aplikasi mobile.
Struktur Proyek
app/
├── Http/
│ ├── Controllers/
│ │ ├── AbsensiController.php
│ │ ├── DashboardController.php
│ │ ├── KelasController.php
│ │ ├── LaporanController.php
│ │ ├── SiswaController.php
│ │ ├── UserController.php
│ │ └── Api/
│ │ ├── AbsensiMobileController.php
│ │ ├── AuthController.php
│ │ ├── ServerStatusController.php
│ │ └── SiswaController.php
│ ├── Middleware/
│ │ └── ValidateApiKey.php
│ └── Requests/
├── Models/
│ ├── Absensi.php
│ ├── Kelas.php
│ ├── Siswa.php
│ └── User.php
└── Providers/
Model
Model merepresentasikan struktur data dan logika bisnis aplikasi. Berikut adalah model utama dalam aplikasi:
User.php
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
protected $fillable = [
'name',
'email',
'password',
'role',
];
protected $hidden = [
'password',
'remember_token',
];
protected $casts = [
'email_verified_at' => 'datetime',
'password' => 'hashed',
];
}
Kelas.php
class Kelas extends Model
{
use HasFactory;
protected $fillable = [
'nama_kelas',
'deskripsi',
];
public function siswa()
{
return $this->hasMany(Siswa::class);
}
}
Siswa.php
class Siswa extends Model
{
use HasFactory;
protected $fillable = [
'id_siswa',
'nama',
'password',
'kelas_id',
'alamat',
'no_telp',
'email',
];
protected $hidden = [
'password',
];
protected $casts = [
'password' => 'hashed',
];
public function kelas()
{
return $this->belongsTo(Kelas::class);
}
public function absensi()
{
return $this->hasMany(Absensi::class);
}
}
Absensi.php
class Absensi extends Model
{
use HasFactory;
protected $fillable = [
'siswa_id',
'tanggal',
'waktu_masuk',
'waktu_keluar',
'status',
'lokasi_masuk',
'lokasi_keluar',
];
public function siswa()
{
return $this->belongsTo(Siswa::class);
}
}
Controller
Controller menangani logika aplikasi dan menghubungkan model dengan view. Berikut adalah controller utama dalam aplikasi:
AbsensiController
Mengelola data absensi siswa, termasuk:
- Menampilkan daftar absensi
- Menambahkan absensi manual
- Mengubah status absensi
- Mengedit detail absensi
DashboardController
Mengelola tampilan dashboard, termasuk:
- Menampilkan statistik absensi
- Menampilkan grafik absensi per tanggal
- Menampilkan grafik absensi per kelas
- Menampilkan grafik status absensi
LaporanController
Mengelola laporan absensi, termasuk:
- Menampilkan laporan absensi berdasarkan filter
- Mengunduh laporan absensi dalam format Excel
API Controller
Controller API digunakan untuk menyediakan endpoint untuk aplikasi mobile:
- AuthController - Menangani autentikasi siswa
- AbsensiMobileController - Menangani absensi masuk dan keluar
- ServerStatusController - Menangani pengecekan status server
Middleware
Middleware berfungsi sebagai filter untuk request HTTP. Berikut adalah middleware utama dalam aplikasi:
ValidateApiKey
Middleware ini digunakan untuk memvalidasi API key yang dikirimkan oleh aplikasi mobile. API key disimpan dalam file .env dan dibandingkan dengan API key yang dikirimkan dalam header Authorization.
class ValidateApiKey
{
public function handle(Request $request, Closure $next): Response
{
// Ambil API key dari .env
$validApiKey = env('MOBILE_API_KEY');
// Ambil API key dari header Authorization
$providedApiKey = $request->header('Authorization');
// Support format: "Bearer <api_key>" atau langsung "<api_key>"
if ($providedApiKey && str_starts_with($providedApiKey, 'Bearer ')) {
$providedApiKey = substr($providedApiKey, 7);
}
if (!$providedApiKey || $providedApiKey !== $validApiKey) {
return response()->json([
'success' => false,
'message' => 'Unauthorized: Invalid API key',
], 401);
}
return $next($request);
}
}
Route
Route menentukan bagaimana aplikasi merespons request ke URL tertentu. Berikut adalah route utama dalam aplikasi:
Web Route
// routes/web.php
Route::get('/', function () {
return redirect()->route('login');
});
Route::middleware('auth')->group(function () {
Route::get('/dashboard', [DashboardController::class, 'index'])->name('dashboard');
});
Admin Route
// routes/admin.php
Route::middleware(['auth', 'role:admin,guru'])->group(function () {
// Kelas Routes
Route::resource('kelas', KelasController::class);
// Siswa Routes
Route::resource('siswa', SiswaController::class);
// User Routes
Route::resource('users', UserController::class);
// Laporan Routes
Route::get('laporan', [LaporanController::class, 'index'])->name('laporan.index');
Route::get('laporan/download', [LaporanController::class, 'download'])->name('laporan.download');
// Absensi Routes
Route::get('absensi', [AbsensiController::class, 'index'])->name('absensi.index');
Route::get('absensi/create', [AbsensiController::class, 'create'])->name('absensi.create');
Route::post('absensi', [AbsensiController::class, 'store'])->name('absensi.store');
Route::get('absensi/{id}/edit', [AbsensiController::class, 'edit'])->name('absensi.edit');
Route::put('absensi/{id}', [AbsensiController::class, 'update'])->name('absensi.update');
Route::put('absensi/{id}/status', [AbsensiController::class, 'updateStatus'])->name('absensi.updateStatus');
});
API Route
// routes/api.php
// API untuk mendapatkan daftar siswa berdasarkan kelas (untuk admin/guru)
Route::get('/siswa', [SiswaController::class, 'index']);
// API Mobile untuk Android
// API untuk cek status server (untuk scanning dari Android)
Route::get('/mobile/status', [ServerStatusController::class, 'status'])->middleware(ValidateApiKey::class);
// API untuk autentikasi siswa
Route::post('/mobile/auth/login', [AuthController::class, 'login'])->middleware(ValidateApiKey::class);
// API untuk absensi
Route::middleware(ValidateApiKey::class)->group(function () {
// Absensi masuk
Route::post('/mobile/absensi/masuk', [AbsensiMobileController::class, 'absenMasuk']);
// Absensi keluar
Route::post('/mobile/absensi/keluar', [AbsensiMobileController::class, 'absenKeluar']);
// Status absensi hari ini
Route::get('/mobile/absensi/status', [AbsensiMobileController::class, 'statusAbsensi']);
});
Database Migration
Migration digunakan untuk mengelola struktur database. Berikut adalah migration utama dalam aplikasi:
create_users_table
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->enum('role', ['admin', 'guru'])->default('guru');
$table->rememberToken();
$table->timestamps();
});
create_kelas_table
Schema::create('kelas', function (Blueprint $table) {
$table->id();
$table->string('nama_kelas');
$table->text('deskripsi')->nullable();
$table->timestamps();
});
create_siswa_table
Schema::create('siswa', function (Blueprint $table) {
$table->id();
$table->string('id_siswa')->unique();
$table->string('nama');
$table->string('password');
$table->foreignId('kelas_id')->constrained()->onDelete('cascade');
$table->text('alamat')->nullable();
$table->string('no_telp')->nullable();
$table->string('email')->nullable();
$table->timestamps();
});
create_absensi_table
Schema::create('absensi', function (Blueprint $table) {
$table->id();
$table->foreignId('siswa_id')->constrained()->onDelete('cascade');
$table->date('tanggal');
$table->time('waktu_masuk')->nullable();
$table->time('waktu_keluar')->nullable();
$table->enum('status', ['hadir', 'sakit', 'izin', 'alpha'])->default('alpha');
$table->string('lokasi_masuk')->nullable();
$table->string('lokasi_keluar')->nullable();
$table->timestamps();
});
Seeder
Seeder digunakan untuk mengisi database dengan data awal. Berikut adalah seeder utama dalam aplikasi:
UserSeeder
public function run(): void
{
// Admin
User::create([
'name' => 'Admin',
'email' => 'admin@example.com',
'password' => Hash::make('password'),
'role' => 'admin',
]);
// Guru
User::create([
'name' => 'Guru',
'email' => 'guru@example.com',
'password' => Hash::make('password'),
'role' => 'guru',
]);
}
KelasSeeder
public function run(): void
{
// Membuat kelas dengan nama spesifik
Kelas::factory()->createMany([
['nama_kelas' => 'X IPA 1'],
['nama_kelas' => 'X IPA 2'],
['nama_kelas' => 'X IPS 1'],
['nama_kelas' => 'X IPS 2'],
['nama_kelas' => 'XI IPA 1'],
['nama_kelas' => 'XI IPA 2'],
['nama_kelas' => 'XI IPS 1'],
['nama_kelas' => 'XI IPS 2'],
['nama_kelas' => 'XII IPA 1'],
['nama_kelas' => 'XII IPA 2'],
['nama_kelas' => 'XII IPS 1'],
['nama_kelas' => 'XII IPS 2'],
]);
}
SiswaSeeder
public function run(): void
{
// Ambil semua ID kelas
$kelasIds = Kelas::pluck('id')->toArray();
// Buat 10 siswa untuk setiap kelas
foreach ($kelasIds as $kelasId) {
Siswa::factory()->count(10)->create([
'kelas_id' => $kelasId,
]);
}
// Buat satu siswa dengan data spesifik
Siswa::factory()->create([
'id_siswa' => 'S123456',
'nama' => 'Budi Santoso',
'password' => Hash::make('password'),
'kelas_id' => $kelasIds[0],
'alamat' => 'Jl. Contoh No. 123, Jakarta',
'no_telp' => '081234567890',
'email' => 'budi@example.com',
]);
}
AbsensiSeeder
public function run(): void
{
// Ambil semua ID siswa
$siswaIds = Siswa::pluck('id')->toArray();
// Buat absensi untuk 30 hari terakhir
$startDate = Carbon::now()->subDays(30);
$endDate = Carbon::now();
for ($date = $startDate; $date->lte($endDate); $date->addDay()) {
// Lewati hari Minggu
if ($date->dayOfWeek === Carbon::SUNDAY) {
continue;
}
foreach ($siswaIds as $siswaId) {
// 80% kemungkinan siswa hadir
if (rand(1, 100) <= 80) {
Absensi::factory()->create([
'siswa_id' => $siswaId,
'tanggal' => $date->format('Y-m-d'),
]);
}
}
}
}
Kesimpulan
Backend Laravel menyediakan fondasi yang kuat untuk aplikasi Absensi GPS, dengan fitur-fitur seperti:
- Model yang merepresentasikan struktur data
- Controller yang menangani logika aplikasi
- Middleware untuk validasi API key
- Route untuk menentukan endpoint
- Migration untuk mengelola struktur database
- Seeder untuk mengisi data awal
Dengan struktur ini, backend dapat mengelola data absensi dengan efisien dan menyediakan API yang aman untuk frontend dan aplikasi mobile.