MODUL PEMROGRAMAN WEBSITE 2
Mata Kuliah: Pemrograman Website 2
Kode MK: INF2419
SKS: 3 (Praktikum)
Semester: Genap 2025/2026
Program Studi: Informatika
Fakultas: FEBI / Saintek
Universitas: UIN K.H. Abdurrahman Wahid Pekalongan
Dosen Pengampu: Mohammad Reza Maulana, M.Kom
NIP: 199110082025051002
Pertemuan: 10 dari 16
Durasi: 150 menit (3 Ã 50 menit)
Studi Kasus Berkelanjutan: Sistem Manajemen Perpustakaan
PERTEMUAN 10
DATABASE DENGAN MIGRATION & MODEL
A. INFORMASI PERTEMUAN
| Aspek | Keterangan |
|---|---|
| Capaian Pembelajaran Lulusan (CPL) | CPL05: Memiliki pengetahuan memadai tentang cara kerja sistem komputer dan mampu merancang solusi algoritmik menggunakan framework. |
| Capaian Pembelajaran Mata Kuliah (CPMK) | CPMK05.1: Mampu merancang struktur aplikasi web backend berbasis framework dengan pendekatan MVC. |
| Sub-CPMK | Sub-CPMK05.1.2: Mampu menjelaskan struktur folder dan alur kerja framework Laravel. |
| Indikator Pencapaian | Mahasiswa mampu: 1. Menjelaskan konsep database migration di Laravel 2. Membuat migration untuk tabel database 3. Menjalankan dan rollback migration 4. Memahami konsep Eloquent ORM 5. Membuat Model dan relasi dengan database 6. Menggunakan database seeding untuk data awal 7. Menerapkan migration & model dalam sistem perpustakaan |
| Alokasi Waktu | âĸ Teori: 60 menit âĸ Praktikum: 90 menit âĸ Total: 150 menit (3 Ã 50 menit) |
B. PENDAHULUAN
1. Deskripsi Singkat
Pertemuan kesepuluh ini membahas pengelolaan database menggunakan Laravel Migration dan Eloquent ORM. Migration memungkinkan version control untuk struktur database, sedangkan Eloquent menyediakan cara elegan untuk berinteraksi dengan database menggunakan konsep OOP. Mahasiswa akan mempelajari cara membuat, menjalankan, dan memanipulasi struktur database melalui migration, serta membuat Model untuk representasi tabel database.
2. Keterkaitan dengan Pertemuan Lain
Pertemuan ini merupakan fondasi penting untuk pengembangan aplikasi Laravel:
- Pertemuan 6: Melanjutkan konsep database MySQL yang telah dipelajari
- Pertemuan 7: Migration menggantikan cara manual membuat tabel dengan SQL
- Pertemuan 9: Menggunakan Laravel project yang telah dibuat
- Pertemuan 11-13: Model akan digunakan intensif untuk CRUD operations
- Pertemuan 14-15: Relasi antar model untuk fitur transaksi
3. Manfaat Pembelajaran
- Mampu mengelola struktur database dengan version control
- Dapat bekerja tim dengan migration yang konsisten
- Memahami ORM untuk interaksi database yang lebih mudah
- Siap mengimplementasikan CRUD dengan Eloquent
- Menguasai best practice Laravel database management
4. Relevansi dengan Studi Kasus
Dalam sistem perpustakaan, migration & model digunakan untuk:
- Membuat struktur tabel buku, anggota, transaksi
- Version control perubahan struktur database
- Eloquent Model untuk operasi CRUD
- Seeding data sample untuk testing
- Relasi antar tabel (buku-transaksi, anggota-transaksi)
C. MATERI TEORI
1. Konsep Database Migration
a. Apa itu Migration?
Migration adalah sistem version control untuk database schema. Migration memungkinkan tim developer untuk:
- Mendefinisikan dan membagikan struktur database aplikasi
- Memodifikasi database schema dengan mudah
- Rollback perubahan jika terjadi masalah
- Tracking perubahan struktur database
Analogi: Migration seperti Git untuk database - setiap perubahan tercatat dan bisa di-undo.
b. Mengapa Menggunakan Migration?
Tanpa Migration (Cara Lama):
-- Developer A membuat tabel manual
CREATE TABLE buku (
id INT PRIMARY KEY AUTO_INCREMENT,
judul VARCHAR(200)
);
-- Developer B tidak tahu perubahan ini
-- Database tidak sync
-- Deployment ke production riskyDengan Migration:
// File migration yang bisa di-commit ke Git
Schema::create('buku', function (Blueprint $table) {
$table->id();
$table->string('judul', 200);
$table->timestamps();
});
// Semua developer jalankan: php artisan migrate
// Database otomatis syncKeuntungan Migration:
- â Version control untuk database
- â Mudah rollback jika error
- â Konsisten di semua environment (dev, staging, production)
- â Dokumentasi otomatis perubahan database
- â Kolaborasi tim lebih mudah
c. Struktur Migration File
Migration file Laravel memiliki 2 method utama:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
* Method ini dijalankan saat: php artisan migrate
*/
public function up(): void
{
Schema::create('buku', function (Blueprint $table) {
// Definisi struktur tabel
});
}
/**
* Reverse the migrations.
* Method ini dijalankan saat: php artisan migrate:rollback
*/
public function down(): void
{
Schema::dropIfExists('buku');
}
};Penjelasan:
up(): Jalankan perubahan (create, modify table)down(): Batalkan perubahan (drop, revert table)
d. Migration Workflow
1. Developer buat migration file
â
2. Definisikan schema di method up()
â
3. Commit file migration ke Git
â
4. Team pull dari Git
â
5. Jalankan: php artisan migrate
â
6. Database semua orang sync2. Laravel Schema Builder
a. Tipe Data Column
Laravel menyediakan banyak method untuk mendefinisikan column:
| Method | Tipe Data SQL | Keterangan |
|---|---|---|
$table->id() | BIGINT UNSIGNED (PK) | Primary key auto increment |
$table->string('nama') | VARCHAR(255) | String default 255 char |
$table->string('nama', 100) | VARCHAR(100) | String custom length |
$table->text('deskripsi') | TEXT | Text panjang |
$table->integer('stok') | INT | Integer |
$table->bigInteger('jumlah') | BIGINT | Integer besar |
$table->decimal('harga', 10, 2) | DECIMAL(10,2) | Decimal (harga) |
$table->boolean('aktif') | BOOLEAN | True/False |
$table->date('tanggal') | DATE | Date only |
$table->dateTime('waktu') | DATETIME | Date + time |
$table->timestamps() | created_at, updated_at | Auto timestamp |
$table->softDeletes() | deleted_at | Soft delete |
Contoh Penggunaan:
Schema::create('buku', function (Blueprint $table) {
$table->id(); // Primary key
$table->string('kode_buku', 20)->unique(); // Unique constraint
$table->string('judul', 200); // Required
$table->string('isbn', 20)->nullable(); // Optional
$table->text('deskripsi')->nullable(); // Text optional
$table->integer('stok')->default(0); // Default value
$table->decimal('harga', 10, 2); // Price
$table->year('tahun_terbit'); // Year
$table->timestamps(); // created_at, updated_at
});b. Column Modifiers
Modifier untuk mengubah behavior column:
$table->string('email')->nullable(); // Boleh NULL
$table->string('kode')->unique(); // Harus unique
$table->integer('stok')->default(0); // Default value
$table->string('status')->default('aktif'); // Default string
$table->string('judul')->comment('Judul buku'); // Comment
$table->integer('urutan')->unsigned(); // Tidak boleh negatif
$table->text('deskripsi')->nullable()->default(null);c. Index & Constraint
// Primary Key (otomatis dengan id())
$table->id();
// Unique
$table->string('email')->unique();
// atau
$table->unique('email');
// Index (untuk performa query)
$table->index('kode_buku');
$table->index(['kategori', 'tahun']); // Composite index
// Foreign Key (akan dipelajari detail di pertemuan 14)
$table->foreignId('kategori_id')
->constrained('kategoris')
->onDelete('cascade');d. Memodifikasi Table
Menambah Column:
Schema::table('buku', function (Blueprint $table) {
$table->string('penerbit', 100)->after('pengarang');
$table->string('bahasa', 20)->default('Indonesia');
});Mengubah Column:
Schema::table('buku', function (Blueprint $table) {
$table->string('judul', 300)->change(); // Ubah length
$table->integer('stok')->unsigned()->change(); // Tambah unsigned
});Menghapus Column:
Schema::table('buku', function (Blueprint $table) {
$table->dropColumn('isbn');
$table->dropColumn(['isbn', 'bahasa']); // Multiple
});Rename Column:
Schema::table('buku', function (Blueprint $table) {
$table->renameColumn('judul', 'title');
});3. Eloquent ORM (Object-Relational Mapping)
a. Apa itu Eloquent?
Eloquent adalah ORM (Object-Relational Mapping) Laravel yang memungkinkan interaksi dengan database menggunakan object-oriented syntax.
Tanpa ORM (Raw SQL):
$hasil = DB::select('SELECT * FROM buku WHERE kategori = ?', ['Programming']);
foreach ($hasil as $row) {
echo $row->judul;
}Dengan Eloquent:
$buku = Buku::where('kategori', 'Programming')->get();
foreach ($buku as $item) {
echo $item->judul;
}Keuntungan Eloquent:
- â Syntax lebih mudah dan readable
- â Type hinting dan auto-completion
- â Relasi antar tabel lebih mudah
- â Built-in validation
- â Events & observers
- â Soft deletes
- â Mass assignment protection
b. Struktur Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Buku extends Model
{
use HasFactory;
// Nama tabel (opsional jika mengikuti convention)
protected $table = 'buku';
// Primary key (opsional jika 'id')
protected $primaryKey = 'id';
// Tipe primary key
protected $keyType = 'int';
// Auto increment
public $incrementing = true;
// Timestamps (created_at, updated_at)
public $timestamps = true;
// Fillable (mass assignment)
protected $fillable = [
'kode_buku',
'judul',
'kategori',
'pengarang',
'penerbit',
'tahun_terbit',
'isbn',
'harga',
'stok',
];
// Guarded (kebalikan fillable)
// protected $guarded = ['id'];
// Hidden (tidak ditampilkan di JSON)
protected $hidden = [];
// Casts (konversi tipe data)
protected $casts = [
'tahun_terbit' => 'integer',
'harga' => 'decimal:2',
'stok' => 'integer',
];
}c. Naming Convention
Laravel menggunakan convention over configuration:
| Item | Convention | Contoh |
|---|---|---|
| Model Name | Singular, PascalCase | Buku, Anggota |
| Table Name | Plural, snake_case | bukus, anggotas |
| Primary Key | id | Auto |
| Foreign Key | model_id | buku_id, anggota_id |
| Timestamps | created_at, updated_at | Auto |
Mengikuti Convention:
// Model: Buku
// Table: bukus (otomatis plural)
class Buku extends Model {}Custom Table Name:
// Jika table name tidak mengikuti convention
class Buku extends Model {
protected $table = 'buku'; // Tanpa 's'
}d. Mass Assignment
Mass assignment memungkinkan insert/update banyak field sekaligus.
Fillable (Whitelist - Recommended):
class Buku extends Model {
protected $fillable = [
'judul',
'pengarang',
'harga',
'stok'
];
}
// Usage
Buku::create([
'judul' => 'Laravel 12',
'pengarang' => 'John Doe',
'harga' => 100000,
'stok' => 10
]);Guarded (Blacklist):
class Buku extends Model {
protected $guarded = ['id', 'created_at', 'updated_at'];
// Semua field boleh kecuali yang di-guarded
}â ī¸ Security Note:
Selalu gunakan $fillable atau $guarded untuk mencegah mass assignment vulnerability.
4. Database Seeding
a. Apa itu Seeding?
Seeding adalah proses mengisi database dengan data sample/dummy untuk testing.
Kegunaan:
- Development: Data dummy untuk testing
- Testing: Data konsisten untuk unit test
- Demo: Data sample untuk presentasi
- Production: Data initial (kategori, roles, dll)
b. Struktur Seeder
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\Buku;
class BukuSeeder extends Seeder
{
public function run(): void
{
// Insert satu record
Buku::create([
'kode_buku' => 'BK-001',
'judul' => 'Laravel 12 Fundamentals',
'kategori' => 'Programming',
'pengarang' => 'John Doe',
'penerbit' => 'Tech Publisher',
'tahun_terbit' => 2024,
'harga' => 150000,
'stok' => 20
]);
// Insert multiple records
$bukuList = [
[
'kode_buku' => 'BK-002',
'judul' => 'MySQL Advanced',
'kategori' => 'Database',
// ...
],
// ... more data
];
foreach ($bukuList as $buku) {
Buku::create($buku);
}
}
}c. Model Factories
Factory untuk generate data dummy secara otomatis:
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
class BukuFactory extends Factory
{
public function definition(): array
{
return [
'kode_buku' => 'BK-' . $this->faker->unique()->numberBetween(1000, 9999),
'judul' => $this->faker->sentence(3),
'kategori' => $this->faker->randomElement(['Programming', 'Database', 'Web Design']),
'pengarang' => $this->faker->name(),
'penerbit' => $this->faker->company(),
'tahun_terbit' => $this->faker->year(),
'harga' => $this->faker->numberBetween(50000, 200000),
'stok' => $this->faker->numberBetween(0, 50),
];
}
}Usage:
// Generate 50 buku dummy
Buku::factory()->count(50)->create();5. Artisan Commands untuk Migration
a. Migration Commands
# Membuat migration baru
php artisan make:migration create_buku_table
php artisan make:migration create_anggota_table
# Membuat migration dengan model sekaligus
php artisan make:model Buku -m
php artisan make:model Anggota -m
# Menjalankan migration
php artisan migrate
# Rollback migration terakhir
php artisan migrate:rollback
# Rollback semua migration
php artisan migrate:reset
# Rollback dan re-run semua migration
php artisan migrate:refresh
# Rollback dan re-run dengan seeding
php artisan migrate:refresh --seed
# Drop semua table dan re-migrate
php artisan migrate:fresh
# Drop, re-migrate, dan seed
php artisan migrate:fresh --seed
# Lihat status migration
php artisan migrate:statusb. Model Commands
# Membuat model
php artisan make:model Buku
# Membuat model + migration
php artisan make:model Buku -m
# Membuat model + migration + seeder
php artisan make:model Buku -ms
# Membuat model + migration + factory + seeder
php artisan make:model Buku -mfs
# Membuat model + controller + migration
php artisan make:model Buku -mc
# All in one (model + migration + factory + seeder + controller)
php artisan make:model Buku -ac. Seeder Commands
# Membuat seeder
php artisan make:seeder BukuSeeder
# Menjalankan seeder
php artisan db:seed
# Menjalankan seeder tertentu
php artisan db:seed --class=BukuSeeder
# Fresh migrate + seed
php artisan migrate:fresh --seed6. Environment Configuration
a. Database Configuration
File: .env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=perpustakaan_laravel
DB_USERNAME=root
DB_PASSWORD=Penjelasan:
DB_CONNECTION: Driver database (mysql, pgsql, sqlite, sqlsrv)DB_HOST: Host database serverDB_PORT: Port database (MySQL default: 3306)DB_DATABASE: Nama databaseDB_USERNAME: Username databaseDB_PASSWORD: Password database
b. Membuat Database
Sebelum migrate, buat database terlebih dahulu:
Via phpMyAdmin:
- Buka http://localhost/phpmyadmin (opens in a new tab)
- Klik "New"
- Database name:
perpustakaan_laravel - Collation:
utf8mb4_unicode_ci - Create
Via Command Line:
mysql -u root -p
CREATE DATABASE perpustakaan_laravel CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
exit;Via Laravel:
// Tidak recommended, tapi bisa
DB::statement('CREATE DATABASE IF NOT EXISTS perpustakaan_laravel');D. PRAKTIKUM
1. Tujuan Praktikum
- Konfigurasi database Laravel
- Membuat migration untuk tabel buku dan anggota
- Menjalankan migration
- Membuat Model Buku dan Anggota
- Membuat seeder untuk data sample
- Memahami rollback migration
- Testing CRUD sederhana dengan Eloquent
2. PRAKTIKUM 1: Konfigurasi Database Laravel
Tujuan
Setup dan konfigurasi koneksi database Laravel.
Langkah-langkah
a. Buat Database
- Buka phpMyAdmin:
http://localhost/phpmyadmin - Klik tab "Databases"
- Database name:
perpustakaan_laravel - Collation:
utf8mb4_unicode_ci - Klik "Create"
b. Konfigurasi .env
Edit file .env di root project Laravel:
APP_NAME="Perpustakaan Laravel"
APP_ENV=local
APP_KEY=base64:xxxxx (biarkan apa adanya)
APP_DEBUG=true
APP_URL=http://localhost:8000
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=perpustakaan_laravel
DB_USERNAME=root
DB_PASSWORD=c. Testing Koneksi
Buat route testing di routes/web.php:
<?php
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\DB;
Route::get('/', function () {
return view('welcome');
});
// Route test koneksi database
Route::get('/test-db', function () {
try {
DB::connection()->getPdo();
$dbName = DB::connection()->getDatabaseName();
return "Koneksi database berhasil!<br />Database: <strong>{$dbName}</strong>";
} catch (\Exception $e) {
return "Koneksi database gagal!<br />Error: " . $e->getMessage();
}
});d. Testing
- Pastikan server Laravel jalan:
php artisan serve - Akses:
http://localhost:8000/test-db - Jika berhasil, akan muncul: "Koneksi database berhasil! Database: perpustakaan_laravel"
Troubleshooting:
| Error | Solusi |
|---|---|
| SQLSTATE[HY000] [1049] Unknown database | Database belum dibuat di phpMyAdmin |
| SQLSTATE[HY000] [2002] Connection refused | MySQL belum running (start XAMPP) |
| Access denied for user 'root'@'localhost' | Username/password salah di .env |
3. PRAKTIKUM 2: Migration Tabel Buku
Tujuan
Membuat migration untuk tabel buku perpustakaan.
Langkah-langkah
a. Buat Migration File
php artisan make:migration create_buku_tableOutput:
Created Migration: 2024_02_10_123456_create_buku_table.phpb. Edit Migration File
File: database/migrations/2024_02_10_123456_create_buku_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('buku', function (Blueprint $table) {
$table->id();
$table->string('kode_buku', 20)->unique();
$table->string('judul', 200);
$table->enum('kategori', [
'Programming',
'Database',
'Web Design',
'Networking',
'Data Science'
]);
$table->string('pengarang', 100);
$table->string('penerbit', 100);
$table->year('tahun_terbit');
$table->string('isbn', 20)->nullable();
$table->decimal('harga', 10, 2);
$table->integer('stok')->default(0);
$table->text('deskripsi')->nullable();
$table->string('bahasa', 20)->default('Indonesia');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('buku');
}
};c. Jalankan Migration
php artisan migrateOutput:
Migrating: 2024_02_10_123456_create_buku_table
Migrated: 2024_02_10_123456_create_buku_table (50.23ms)d. Verifikasi di phpMyAdmin
- Buka phpMyAdmin
- Pilih database
perpustakaan_laravel - Lihat tabel
bukusudah terbuat - Cek struktur tabel (columns, types, indexes)
e. Cek Status Migration
php artisan migrate:statusOutput:
Migration name .................... Batch / Status
2019_12_14_000001_create_personal_access_tokens_table .. [1] Ran
2024_02_10_123456_create_buku_table ................... [1] Ran4. PRAKTIKUM 3: Migration Tabel Anggota
Tujuan
Membuat migration untuk tabel anggota perpustakaan.
Langkah-langkah
a. Buat Migration
php artisan make:migration create_anggota_tableb. Edit Migration File
File: database/migrations/2024_02_10_123457_create_anggota_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('anggota', function (Blueprint $table) {
$table->id();
$table->string('kode_anggota', 20)->unique();
$table->string('nama', 100);
$table->string('email', 100)->unique();
$table->string('telepon', 15);
$table->text('alamat');
$table->date('tanggal_lahir');
$table->enum('jenis_kelamin', ['Laki-laki', 'Perempuan']);
$table->string('pekerjaan', 50)->nullable();
$table->date('tanggal_daftar');
$table->enum('status', ['Aktif', 'Nonaktif'])->default('Aktif');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('anggota');
}
};c. Jalankan Migration
php artisan migrateOutput:
Migrating: 2024_02_10_123457_create_anggota_table
Migrated: 2024_02_10_123457_create_anggota_table (45.12ms)d. Verifikasi
Cek di phpMyAdmin bahwa tabel anggota sudah terbuat dengan struktur yang benar.
5. PRAKTIKUM 4: Membuat Model Eloquent
Tujuan
Membuat Model untuk tabel buku dan anggota.
Langkah-langkah
a. Buat Model Buku
php artisan make:model BukuOutput:
Model created successfully.b. Edit Model Buku
File: app/Models/Buku.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Buku extends Model
{
use HasFactory;
/**
* Nama tabel yang digunakan oleh model ini.
*
* @var string
*/
protected $table = 'buku';
/**
* Kolom yang dapat diisi secara mass assignment.
*
* @var array<int, string>
*/
protected $fillable = [
'kode_buku',
'judul',
'kategori',
'pengarang',
'penerbit',
'tahun_terbit',
'isbn',
'harga',
'stok',
'deskripsi',
'bahasa',
];
/**
* Tipe casting untuk atribut.
*
* @var array<string, string>
*/
protected $casts = [
'tahun_terbit' => 'integer',
'harga' => 'decimal:2',
'stok' => 'integer',
];
/**
* Accessor untuk format harga.
*/
public function getHargaFormatAttribute(): string
{
return 'Rp ' . number_format($this->harga, 0, ',', '.');
}
/**
* Accessor untuk status ketersediaan.
*/
public function getTersediaAttribute(): bool
{
return $this->stok > 0;
}
/**
* Scope untuk filter buku tersedia.
*/
public function scopeTersedia($query)
{
return $query->where('stok', '>', 0);
}
/**
* Scope untuk filter berdasarkan kategori.
*/
public function scopeKategori($query, $kategori)
{
return $query->where('kategori', $kategori);
}
}c. Buat Model Anggota
php artisan make:model Anggotad. Edit Model Anggota
File: app/Models/Anggota.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Carbon\Carbon;
class Anggota extends Model
{
use HasFactory;
/**
* Nama tabel yang digunakan oleh model ini.
*
* @var string
*/
protected $table = 'anggota';
/**
* Kolom yang dapat diisi secara mass assignment.
*
* @var array<int, string>
*/
protected $fillable = [
'kode_anggota',
'nama',
'email',
'telepon',
'alamat',
'tanggal_lahir',
'jenis_kelamin',
'pekerjaan',
'tanggal_daftar',
'status',
];
/**
* Tipe casting untuk atribut.
*
* @var array<string, string>
*/
protected $casts = [
'tanggal_lahir' => 'date',
'tanggal_daftar' => 'date',
];
/**
* Accessor untuk menghitung umur.
*/
public function getUmurAttribute(): int
{
return Carbon::parse($this->tanggal_lahir)->age;
}
/**
* Accessor untuk lama menjadi anggota (dalam hari).
*/
public function getLamaAnggotaAttribute(): int
{
return Carbon::parse($this->tanggal_daftar)->diffInDays(now());
}
/**
* Scope untuk filter anggota aktif.
*/
public function scopeAktif($query)
{
return $query->where('status', 'Aktif');
}
/**
* Scope untuk filter berdasarkan jenis kelamin.
*/
public function scopeJenisKelamin($query, $jenisKelamin)
{
return $query->where('jenis_kelamin', $jenisKelamin);
}
}e. Test Model via Tinker
Laravel Tinker adalah REPL (Read-Eval-Print-Loop) untuk testing code PHP secara interaktif.
php artisan tinkerDi Tinker, test model:
// Test Buku Model
>>> $buku = new App\Models\Buku();
>>> $buku->judul = "Test Laravel 12";
>>> $buku->kategori = "Programming";
>>> $buku->harga = 150000;
>>> $buku // Lihat object
// Test Anggota Model
>>> $anggota = new App\Models\Anggota();
>>> $anggota->nama = "John Doe";
>>> $anggota->email = "john@example.com";
>>> $anggota // Lihat object
// Keluar dari tinker
>>> exit6. PRAKTIKUM 5: Database Seeding
Tujuan
Membuat seeder untuk mengisi data sample buku dan anggota.
Langkah-langkah
a. Buat Seeder Buku
php artisan make:seeder BukuSeederb. Edit BukuSeeder
File: database/seeders/BukuSeeder.php
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\Buku;
class BukuSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
$bukuList = [
[
'kode_buku' => 'BK-001',
'judul' => 'Laravel 12 untuk Pemula',
'kategori' => 'Programming',
'pengarang' => 'John Doe',
'penerbit' => 'Tech Publisher',
'tahun_terbit' => 2024,
'isbn' => '978-602-1234-56-1',
'harga' => 150000,
'stok' => 20,
'deskripsi' => 'Buku panduan lengkap Laravel 12 dari dasar hingga mahir',
'bahasa' => 'Indonesia',
],
[
'kode_buku' => 'BK-002',
'judul' => 'MySQL Advanced Techniques',
'kategori' => 'Database',
'pengarang' => 'Jane Smith',
'penerbit' => 'Data Press',
'tahun_terbit' => 2023,
'isbn' => '978-602-1234-56-2',
'harga' => 175000,
'stok' => 15,
'deskripsi' => 'Teknik advanced untuk optimasi MySQL database',
'bahasa' => 'Inggris',
],
[
'kode_buku' => 'BK-003',
'judul' => 'Modern Web Design',
'kategori' => 'Web Design',
'pengarang' => 'Ahmad Yani',
'penerbit' => 'Creative Media',
'tahun_terbit' => 2024,
'isbn' => '978-602-1234-56-3',
'harga' => 120000,
'stok' => 25,
'deskripsi' => 'Prinsip dan praktik desain web modern',
'bahasa' => 'Indonesia',
],
[
'kode_buku' => 'BK-004',
'judul' => 'Network Security Fundamentals',
'kategori' => 'Networking',
'pengarang' => 'Robert Johnson',
'penerbit' => 'Security Press',
'tahun_terbit' => 2023,
'isbn' => '978-602-1234-56-4',
'harga' => 200000,
'stok' => 10,
'deskripsi' => 'Dasar-dasar keamanan jaringan komputer',
'bahasa' => 'Inggris',
],
[
'kode_buku' => 'BK-005',
'judul' => 'Data Science dengan Python',
'kategori' => 'Data Science',
'pengarang' => 'Siti Nurhaliza',
'penerbit' => 'Analytics Publisher',
'tahun_terbit' => 2024,
'isbn' => '978-602-1234-56-5',
'harga' => 180000,
'stok' => 18,
'deskripsi' => 'Panduan praktis data science menggunakan Python',
'bahasa' => 'Indonesia',
],
[
'kode_buku' => 'BK-006',
'judul' => 'PHP 8 Programming',
'kategori' => 'Programming',
'pengarang' => 'Budi Raharjo',
'penerbit' => 'Code House',
'tahun_terbit' => 2023,
'isbn' => '978-602-1234-56-6',
'harga' => 130000,
'stok' => 0,
'deskripsi' => 'Fitur-fitur terbaru PHP 8',
'bahasa' => 'Indonesia',
],
[
'kode_buku' => 'BK-007',
'judul' => 'PostgreSQL Administration',
'kategori' => 'Database',
'pengarang' => 'David Wilson',
'penerbit' => 'Database Pro',
'tahun_terbit' => 2024,
'isbn' => '978-602-1234-56-7',
'harga' => 195000,
'stok' => 12,
'deskripsi' => 'Administrasi dan optimasi PostgreSQL',
'bahasa' => 'Inggris',
],
[
'kode_buku' => 'BK-008',
'judul' => 'React & Next.js Development',
'kategori' => 'Programming',
'pengarang' => 'Sarah Anderson',
'penerbit' => 'Frontend Press',
'tahun_terbit' => 2024,
'isbn' => '978-602-1234-56-8',
'harga' => 165000,
'stok' => 22,
'deskripsi' => 'Membangun aplikasi modern dengan React dan Next.js',
'bahasa' => 'Inggris',
],
];
foreach ($bukuList as $buku) {
Buku::create($buku);
}
}
}c. Buat Seeder Anggota
php artisan make:seeder AnggotaSeederd. Edit AnggotaSeeder
File: database/seeders/AnggotaSeeder.php
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\Anggota;
use Carbon\Carbon;
class AnggotaSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
$anggotaList = [
[
'kode_anggota' => 'AGT-001',
'nama' => 'Budi Santoso',
'email' => 'budi.santoso@email.com',
'telepon' => '081234567890',
'alamat' => 'Jl. Merdeka No. 10, Jakarta Pusat',
'tanggal_lahir' => '1995-05-15',
'jenis_kelamin' => 'Laki-laki',
'pekerjaan' => 'Mahasiswa',
'tanggal_daftar' => '2024-01-10',
'status' => 'Aktif',
],
[
'kode_anggota' => 'AGT-002',
'nama' => 'Siti Nurhaliza',
'email' => 'siti.nur@email.com',
'telepon' => '081234567891',
'alamat' => 'Jl. Sudirman No. 25, Bandung',
'tanggal_lahir' => '1998-08-20',
'jenis_kelamin' => 'Perempuan',
'pekerjaan' => 'Pegawai Swasta',
'tanggal_daftar' => '2024-01-15',
'status' => 'Aktif',
],
[
'kode_anggota' => 'AGT-003',
'nama' => 'Ahmad Dhani',
'email' => 'ahmad.dhani@email.com',
'telepon' => '081234567892',
'alamat' => 'Jl. Gatot Subroto No. 5, Surabaya',
'tanggal_lahir' => '1992-03-10',
'jenis_kelamin' => 'Laki-laki',
'pekerjaan' => 'Dosen',
'tanggal_daftar' => '2024-02-01',
'status' => 'Aktif',
],
[
'kode_anggota' => 'AGT-004',
'nama' => 'Dewi Lestari',
'email' => 'dewi.lestari@email.com',
'telepon' => '081234567893',
'alamat' => 'Jl. Ahmad Yani No. 30, Yogyakarta',
'tanggal_lahir' => '2000-12-05',
'jenis_kelamin' => 'Perempuan',
'pekerjaan' => 'Mahasiswa',
'tanggal_daftar' => '2024-02-10',
'status' => 'Aktif',
],
[
'kode_anggota' => 'AGT-005',
'nama' => 'Rizky Febian',
'email' => 'rizky.feb@email.com',
'telepon' => '081234567894',
'alamat' => 'Jl. Diponegoro No. 15, Semarang',
'tanggal_lahir' => '1997-07-18',
'jenis_kelamin' => 'Laki-laki',
'pekerjaan' => 'Wiraswasta',
'tanggal_daftar' => '2023-12-15',
'status' => 'Nonaktif',
],
];
foreach ($anggotaList as $anggota) {
Anggota::create($anggota);
}
}
}e. Register Seeder di DatabaseSeeder
File: database/seeders/DatabaseSeeder.php
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*/
public function run(): void
{
$this->call([
BukuSeeder::class,
AnggotaSeeder::class,
]);
}
}f. Jalankan Seeder
# Jalankan semua seeder
php artisan db:seed
# Atau jalankan seeder tertentu
php artisan db:seed --class=BukuSeeder
php artisan db:seed --class=AnggotaSeederOutput:
Seeding: Database\Seeders\BukuSeeder
Seeded: Database\Seeders\BukuSeeder (150.23ms)
Seeding: Database\Seeders\AnggotaSeeder
Seeded: Database\Seeders\AnggotaSeeder (45.12ms)g. Verifikasi Data
- Buka phpMyAdmin
- Pilih database
perpustakaan_laravel - Cek tabel
buku- harus ada 8 records - Cek tabel
anggota- harus ada 5 records
h. Fresh Migration dengan Seed
Jika ingin reset dan seed ulang:
php artisan migrate:fresh --seedCommand ini akan:
- Drop semua tabel
- Re-run semua migration
- Jalankan semua seeder
7. PRAKTIKUM 6: Testing CRUD dengan Tinker
Tujuan
Melakukan testing CRUD operations menggunakan Eloquent ORM via Tinker.
Langkah-langkah
a. Buka Tinker
php artisan tinkerb. READ Operations
// 1. Get all buku
>>> $bukus = App\Models\Buku::all();
>>> $bukus->count() // Jumlah buku
// 2. Get first buku
>>> $buku = App\Models\Buku::first();
>>> $buku->judul
// 3. Find by ID
>>> $buku = App\Models\Buku::find(1);
>>> $buku->judul
>>> $buku->harga_format // Accessor
// 4. Find by kode_buku
>>> $buku = App\Models\Buku::where('kode_buku', 'BK-001')->first();
>>> $buku->judul
// 5. Filter kategori Programming
>>> $bukus = App\Models\Buku::where('kategori', 'Programming')->get();
>>> $bukus->count()
// 6. Filter buku tersedia (stok > 0)
>>> $bukus = App\Models\Buku::tersedia()->get();
>>> $bukus->pluck('judul')
// 7. Filter dengan scope
>>> $bukus = App\Models\Buku::kategori('Database')->get();
>>> $bukus->pluck('judul')
// 8. Chaining query
>>> $bukus = App\Models\Buku::where('kategori', 'Programming')
->where('stok', '>', 10)
->orderBy('harga', 'desc')
->get();c. CREATE Operations
// 1. Create dengan save()
>>> $buku = new App\Models\Buku();
>>> $buku->kode_buku = 'BK-009';
>>> $buku->judul = 'Vue.js 3 Complete Guide';
>>> $buku->kategori = 'Programming';
>>> $buku->pengarang = 'Sarah Chen';
>>> $buku->penerbit = 'Frontend Books';
>>> $buku->tahun_terbit = 2024;
>>> $buku->harga = 145000;
>>> $buku->stok = 15;
>>> $buku->bahasa = 'Inggris';
>>> $buku->save()
>>> $buku->id // Auto increment
// 2. Create dengan mass assignment
>>> App\Models\Buku::create([
'kode_buku' => 'BK-010',
'judul' => 'Docker & Kubernetes',
'kategori' => 'Programming',
'pengarang' => 'Michael Johnson',
'penerbit' => 'DevOps Press',
'tahun_terbit' => 2024,
'harga' => 210000,
'stok' => 8,
'bahasa' => 'Inggris'
])
// Verifikasi
>>> App\Models\Buku::count() // Should be 10 nowd. UPDATE Operations
// 1. Update dengan save()
>>> $buku = App\Models\Buku::find(1);
>>> $buku->stok = 25;
>>> $buku->harga = 155000;
>>> $buku->save()
// 2. Update dengan update()
>>> $buku = App\Models\Buku::find(2);
>>> $buku->update([
'stok' => 20,
'harga' => 180000
])
// 3. Update multiple records
>>> App\Models\Buku::where('kategori', 'Programming')
->update(['stok' => 30])
// Verifikasi
>>> $buku = App\Models\Buku::find(1);
>>> $buku->stok // Should be 25e. DELETE Operations
// 1. Delete dengan delete()
>>> $buku = App\Models\Buku::find(10);
>>> $buku->delete()
// 2. Delete dengan destroy()
>>> App\Models\Buku::destroy(9)
// 3. Delete multiple IDs
>>> App\Models\Buku::destroy([7, 8]) // Jangan jalankan ini!
// 4. Delete with condition
>>> App\Models\Buku::where('stok', 0)->delete() // Hapus buku habis
// Verifikasi
>>> App\Models\Buku::count()f. Testing Anggota Model
// READ
>>> $anggotas = App\Models\Anggota::all();
>>> $anggotas->count()
>>> $anggota = App\Models\Anggota::first();
>>> $anggota->nama
>>> $anggota->umur // Accessor
>>> $anggota->lama_anggota // Accessor
// Filter aktif
>>> $aktif = App\Models\Anggota::aktif()->get();
>>> $aktif->pluck('nama')
// CREATE
>>> App\Models\Anggota::create([
'kode_anggota' => 'AGT-006',
'nama' => 'Testing User',
'email' => 'test@example.com',
'telepon' => '081234567899',
'alamat' => 'Jl. Test No. 1',
'tanggal_lahir' => '2000-01-01',
'jenis_kelamin' => 'Laki-laki',
'pekerjaan' => 'Tester',
'tanggal_daftar' => today(),
'status' => 'Aktif'
])
// Keluar dari Tinker
>>> exit8. PRAKTIKUM 7: Rollback & Modify Migration
Tujuan
Memahami cara rollback migration dan memodifikasi struktur tabel.
Langkah-langkah
a. Cek Status Migration
php artisan migrate:statusb. Rollback Migration Terakhir
php artisan migrate:rollbackIni akan rollback batch migration terakhir (anggota).
Cek di phpMyAdmin - tabel anggota hilang, tabel buku masih ada.
c. Rollback Step
# Rollback 1 step
php artisan migrate:rollback --step=1
# Rollback 2 step
php artisan migrate:rollback --step=2d. Re-migrate
php artisan migratee. Tambah Column ke Tabel Buku
Buat migration baru untuk modify:
php artisan make:migration add_penerbit_detail_to_buku_tableEdit migration file:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('buku', function (Blueprint $table) {
$table->string('negara_penerbit', 50)->nullable()->after('penerbit');
$table->string('kota_penerbit', 50)->nullable()->after('negara_penerbit');
});
}
public function down(): void
{
Schema::table('buku', function (Blueprint $table) {
$table->dropColumn(['negara_penerbit', 'kota_penerbit']);
});
}
};Jalankan migration:
php artisan migrateCek di phpMyAdmin - tabel buku sekarang punya 2 kolom baru.
f. Refresh Migration
# Drop all tables dan re-run semua migration
php artisan migrate:fresh
# Dengan seeding
php artisan migrate:fresh --seedâ ī¸ Warning: migrate:fresh akan menghapus SEMUA data!
9. PRAKTIKUM 8: Route Testing CRUD
Tujuan
Membuat route sederhana untuk testing CRUD via browser.
Langkah-langkah
a. Edit routes/web.php
<?php
use Illuminate\Support\Facades\Route;
use App\Models\Buku;
use App\Models\Anggota;
Route::get('/', function () {
return view('welcome');
});
// ========== TESTING BUKU ==========
// List all buku
Route::get('/buku', function () {
$bukus = Buku::all();
$html = '<h1>Daftar Buku</h1>';
$html .= '<a href="/buku/create">Tambah Buku</a><br /><br />';
$html .= '<table border="1" cellpadding="10">';
$html .= '<tr>
<th>ID</th>
<th>Kode</th>
<th>Judul</th>
<th>Kategori</th>
<th>Harga</th>
<th>Stok</th>
<th>Aksi</th>
</tr>';
foreach ($bukus as $buku) {
$html .= '<tr>';
$html .= '<td>' . $buku->id . '</td>';
$html .= '<td>' . $buku->kode_buku . '</td>';
$html .= '<td>' . $buku->judul . '</td>';
$html .= '<td>' . $buku->kategori . '</td>';
$html .= '<td>' . $buku->harga_format . '</td>';
$html .= '<td>' . $buku->stok . '</td>';
$html .= '<td>
<a href="/buku/' . $buku->id . '">Detail</a> |
<a href="/buku/' . $buku->id . '/edit">Edit</a>
</td>';
$html .= '</tr>';
}
$html .= '</table>';
return $html;
});
// Show single buku
Route::get('/buku/{id}', function ($id) {
$buku = Buku::findOrFail($id);
$html = '<h1>Detail Buku</h1>';
$html .= '<a href="/buku">Kembali</a><br /><br />';
$html .= '<table border="1" cellpadding="10">';
$html .= '<tr><th>Field</th><th>Value</th></tr>';
$html .= '<tr><td>ID</td><td>' . $buku->id . '</td></tr>';
$html .= '<tr><td>Kode Buku</td><td>' . $buku->kode_buku . '</td></tr>';
$html .= '<tr><td>Judul</td><td>' . $buku->judul . '</td></tr>';
$html .= '<tr><td>Kategori</td><td>' . $buku->kategori . '</td></tr>';
$html .= '<tr><td>Pengarang</td><td>' . $buku->pengarang . '</td></tr>';
$html .= '<tr><td>Penerbit</td><td>' . $buku->penerbit . '</td></tr>';
$html .= '<tr><td>Tahun</td><td>' . $buku->tahun_terbit . '</td></tr>';
$html .= '<tr><td>ISBN</td><td>' . $buku->isbn . '</td></tr>';
$html .= '<tr><td>Harga</td><td>' . $buku->harga_format . '</td></tr>';
$html .= '<tr><td>Stok</td><td>' . $buku->stok . '</td></tr>';
$html .= '<tr><td>Tersedia?</td><td>' . ($buku->tersedia ? 'Ya' : 'Tidak') . '</td></tr>';
$html .= '<tr><td>Created</td><td>' . $buku->created_at . '</td></tr>';
$html .= '<tr><td>Updated</td><td>' . $buku->updated_at . '</td></tr>';
$html .= '</table>';
return $html;
});
// ========== TESTING ANGGOTA ==========
// List all anggota
Route::get('/anggota', function () {
$anggotas = Anggota::all();
$html = '<h1>Daftar Anggota</h1>';
$html .= '<table border="1" cellpadding="10">';
$html .= '<tr>
<th>ID</th>
<th>Kode</th>
<th>Nama</th>
<th>Email</th>
<th>Umur</th>
<th>Status</th>
<th>Aksi</th>
</tr>';
foreach ($anggotas as $anggota) {
$html .= '<tr>';
$html .= '<td>' . $anggota->id . '</td>';
$html .= '<td>' . $anggota->kode_anggota . '</td>';
$html .= '<td>' . $anggota->nama . '</td>';
$html .= '<td>' . $anggota->email . '</td>';
$html .= '<td>' . $anggota->umur . ' tahun</td>';
$html .= '<td>' . $anggota->status . '</td>';
$html .= '<td><a href="/anggota/' . $anggota->id . '">Detail</a></td>';
$html .= '</tr>';
}
$html .= '</table>';
return $html;
});
// Show single anggota
Route::get('/anggota/{id}', function ($id) {
$anggota = Anggota::findOrFail($id);
$html = '<h1>Detail Anggota</h1>';
$html .= '<a href="/anggota">Kembali</a><br /><br />';
$html .= '<table border="1" cellpadding="10">';
$html .= '<tr><th>Field</th><th>Value</th></tr>';
$html .= '<tr><td>Kode Anggota</td><td>' . $anggota->kode_anggota . '</td></tr>';
$html .= '<tr><td>Nama</td><td>' . $anggota->nama . '</td></tr>';
$html .= '<tr><td>Email</td><td>' . $anggota->email . '</td></tr>';
$html .= '<tr><td>Telepon</td><td>' . $anggota->telepon . '</td></tr>';
$html .= '<tr><td>Alamat</td><td>' . $anggota->alamat . '</td></tr>';
$html .= '<tr><td>Tanggal Lahir</td><td>' . $anggota->tanggal_lahir->format('d-m-Y') . '</td></tr>';
$html .= '<tr><td>Umur</td><td>' . $anggota->umur . ' tahun</td></tr>';
$html .= '<tr><td>Jenis Kelamin</td><td>' . $anggota->jenis_kelamin . '</td></tr>';
$html .= '<tr><td>Pekerjaan</td><td>' . $anggota->pekerjaan . '</td></tr>';
$html .= '<tr><td>Tanggal Daftar</td><td>' . $anggota->tanggal_daftar->format('d-m-Y') . '</td></tr>';
$html .= '<tr><td>Lama Anggota</td><td>' . $anggota->lama_anggota . ' hari</td></tr>';
$html .= '<tr><td>Status</td><td>' . $anggota->status . '</td></tr>';
$html .= '</table>';
return $html;
});
// Testing Scope & Query
Route::get('/test-query', function () {
$html = '<h1>Testing Query Eloquent</h1>';
// Buku tersedia
$tersedia = Buku::tersedia()->get();
$html .= '<h3>Buku Tersedia (Stok > 0): ' . $tersedia->count() . '</h3>';
$html .= '<ul>';
foreach ($tersedia as $buku) {
$html .= '<li>' . $buku->judul . ' (Stok: ' . $buku->stok . ')</li>';
}
$html .= '</ul>';
// Buku Programming
$programming = Buku::kategori('Programming')->get();
$html .= '<h3>Buku Programming: ' . $programming->count() . '</h3>';
$html .= '<ul>';
foreach ($programming as $buku) {
$html .= '<li>' . $buku->judul . '</li>';
}
$html .= '</ul>';
// Anggota Aktif
$aktif = Anggota::aktif()->get();
$html .= '<h3>Anggota Aktif: ' . $aktif->count() . '</h3>';
$html .= '<ul>';
foreach ($aktif as $anggota) {
$html .= '<li>' . $anggota->nama . ' (' . $anggota->email . ')</li>';
}
$html .= '</ul>';
return $html;
});b. Testing Routes
- Akses:
http://localhost:8000/buku- Lihat daftar semua buku
- Akses:
http://localhost:8000/buku/1- Lihat detail buku ID 1
- Akses:
http://localhost:8000/anggota- Lihat daftar semua anggota
- Akses:
http://localhost:8000/anggota/1- Lihat detail anggota ID 1
- Akses:
http://localhost:8000/test-query- Lihat hasil query dengan scope
E. TUGAS
Tugas 1: Migration Tabel Kategori (40%)
Instruksi:
Buat migration untuk tabel kategori yang akan menyimpan kategori buku secara terpisah (normalisasi database).
Spesifikasi:
- Buat Migration:
php artisan make:migration create_kategori_table-
Struktur Tabel:
id: bigint, primary key, auto incrementnama_kategori: string(50), unique, not nulldeskripsi: text, nullableicon: string(50), nullable (untuk icon Bootstrap)warna: string(20), nullable (untuk badge color)timestamps: created_at, updated_at
-
Buat Model:
php artisan make:model Kategori-
Fillable di Model:
- nama_kategori
- deskripsi
- icon
- warna
-
Buat Seeder: Data kategori:
- Programming (icon: code-slash, warna: primary)
- Database (icon: database, warna: success)
- Web Design (icon: palette, warna: info)
- Networking (icon: wifi, warna: warning)
- Data Science (icon: graph-up, warna: danger)
Tugas 2: Model Accessor & Scope (60%)
Instruksi: Tambahkan accessor dan scope ke Model Buku dan Anggota.
Spesifikasi:
A. Model Buku - Tambahkan:
-
Accessor
status_stok_badge:- Return HTML badge berdasarkan stok:
- Stok = 0:
<span class="badge bg-danger">Habis</span> - Stok 1-5:
<span class="badge bg-warning">Menipis</span> - Stok 6-15:
<span class="badge bg-info">Sedang</span> - Stok > 15:
<span class="badge bg-success">Aman</span>
- Stok = 0:
- Return HTML badge berdasarkan stok:
-
Accessor
tahun_label:- Return "Buku Baru" jika tahun >= 2024
- Return "Buku Lama" jika tahun < 2024
-
Scope
stokMenipis():- Filter buku dengan stok < 5
-
Scope
hargaRange($min, $max):- Filter buku dengan harga antara $min dan $max
-
Scope
terbaru():- Filter buku dengan tahun_terbit >= 2024
B. Model Anggota - Tambahkan:
-
Accessor
status_badge:- Aktif:
<span class="badge bg-success">Aktif</span> - Nonaktif:
<span class="badge bg-secondary">Nonaktif</span>
- Aktif:
-
Accessor
kategori_usia:- Return "Remaja" jika umur < 20
- Return "Dewasa" jika umur 20-50
- Return "Senior" jika umur > 50
-
Scope
jenisKelamin($jk):- Filter berdasarkan jenis kelamin
-
Scope
terdaftarBulanIni():- Filter anggota yang terdaftar di bulan ini
C. Testing Route:
Buat route /test-accessor-scope yang menampilkan:
- Buku dengan status_stok_badge
- Buku terbaru (scope)
- Buku stok menipis (scope)
- Anggota dengan status_badge
- Anggota dengan kategori_usia
- Anggota terdaftar bulan ini (scope)
Template Code:
// Model Buku - Accessor
public function getStatusStokBadgeAttribute(): string
{
// TODO: Implement logic
}
// Model Buku - Scope
public function scopeStokMenipis($query)
{
// TODO: Implement
}
// Testing Route
Route::get('/test-accessor-scope', function () {
$html = '<h1>Testing Accessor & Scope</h1>';
// TODO: Test semua accessor dan scope
return $html;
});Submission:
- Format: Link repository GitHub (sertakan screenshot hasil migration, seeder, dan route testing di README)
- Deadline: Pertemuan 11
- Upload ke: Ngaji UIN Gusdur (submit link repository GitHub)
F. EVALUASI
1. Kuis Singkat (Dikerjakan di Kelas)
Soal Pilihan Ganda:
-
Perintah untuk membuat migration baru adalah:
- A.
php artisan create:migration - B.
php artisan make:migration - C.
php artisan migration:create - D.
php artisan new:migration
- A.
-
Method di migration untuk membatalkan perubahan adalah:
- A.
reverse() - B.
rollback() - C.
down() - D.
undo()
- A.
-
Perintah untuk menjalankan semua migration adalah:
- A.
php artisan migrate - B.
php artisan db:migrate - C.
php artisan migration:run - D.
php artisan run:migrate
- A.
-
Untuk membuat primary key auto increment gunakan:
- A.
$table->primaryKey() - B.
$table->id() - C.
$table->autoIncrement() - D.
$table->pk()
- A.
-
ORM yang digunakan Laravel adalah:
- A. Doctrine
- B. Eloquent
- C. Propel
- D. RedBean
-
Perintah untuk rollback migration terakhir:
- A.
php artisan migrate:undo - B.
php artisan migrate:rollback - C.
php artisan migrate:revert - D.
php artisan migrate:back
- A.
-
Property untuk mass assignment whitelist adalah:
- A.
$allowed - B.
$fillable - C.
$permitted - D.
$writable
- A.
-
Untuk membuat Model dan Migration sekaligus:
- A.
php artisan make:model Buku -m - B.
php artisan make:model Buku --migration - C.
php artisan make:model Buku -c - D. A dan B benar
- A.
-
Method untuk mencari record by primary key:
- A.
Model::get($id) - B.
Model::search($id) - C.
Model::find($id) - D.
Model::where('id', $id)
- A.
-
Perintah untuk fresh migrate + seed:
- A.
php artisan migrate:fresh --seed - B.
php artisan db:fresh --seed - C.
php artisan fresh:seed - D.
php artisan migrate:seed --fresh
- A.
Soal Essay:
-
Jelaskan perbedaan migration dengan cara manual membuat tabel SQL! Apa keuntungan menggunakan migration? (10 poin)
Jawaban tersedia di dokumen kunci jawaban dosen.
-
Apa fungsi
up()dandown()dalam migration? Berikan contoh! (10 poin)Jawaban tersedia di dokumen kunci jawaban dosen.
-
Jelaskan apa itu Eloquent ORM dan apa keuntungannya dibanding raw SQL! (10 poin)
Jawaban tersedia di dokumen kunci jawaban dosen.
-
Buatlah migration untuk membuat tabel 'penerbit' dengan field: id, nama_penerbit, alamat, telepon! (15 poin)
Jawaban tersedia di dokumen kunci jawaban dosen.
-
Apa itu Mass Assignment dan mengapa perlu $fillable/$guarded? (10 poin)
Jawaban tersedia di dokumen kunci jawaban dosen.
2. Checklist Kompetensi
Self-Assessment:
| No | Kompetensi | Belum | Cukup | Mahir |
|---|---|---|---|---|
| 1 | Membuat migration file | â | â | â |
| 2 | Mendefinisikan schema dengan Blueprint | â | â | â |
| 3 | Menjalankan migration | â | â | â |
| 4 | Rollback migration | â | â | â |
| 5 | Membuat Model Eloquent | â | â | â |
| 6 | Menggunakan fillable/guarded | â | â | â |
| 7 | CRUD dengan Eloquent | â | â | â |
| 8 | Membuat accessor | â | â | â |
| 9 | Membuat scope | â | â | â |
| 10 | Database seeding | â | â | â |
Target: Minimal "Cukup" untuk semua poin sebelum lanjut ke pertemuan 11.
G. REFERENSI
1. Dokumentasi Resmi Laravel 12
-
Database: Migrations https://laravel.com/docs/12.x/migrations (opens in a new tab)
-
Eloquent ORM https://laravel.com/docs/12.x/eloquent (opens in a new tab)
-
Database: Seeding https://laravel.com/docs/12.x/seeding (opens in a new tab)
-
Eloquent: Relationships https://laravel.com/docs/12.x/eloquent-relationships (opens in a new tab)
2. Tutorial & Course
- Laravel Daily - Migrations Best Practices
- Laracasts - Eloquent Techniques
- Laravel News - Database Tips
3. Tools
-
Laravel Schema Designer https://laravelsd.com/ (opens in a new tab)
-
Database Diagram Tool https://dbdiagram.io/ (opens in a new tab)
H. CATATAN PENTING
Untuk Mahasiswa:
1. Best Practices Migration
â DO:
// Nama file descriptive
create_buku_table
add_status_to_anggota_table
// Gunakan Blueprint methods
$table->string('judul', 200);
$table->decimal('harga', 10, 2);
// Selalu implement down()
public function down(): void {
Schema::dropIfExists('buku');
}
// Commit migration files ke Gitâ DON'T:
// Jangan edit migration yang sudah di-run di production
// Buat migration baru untuk perubahan
// Jangan hardcode values
$table->string('status')->default('aktif'); // â
$table->enum('status', ['aktif', 'nonaktif'])->default('aktif'); //
// Jangan lupa timestamps
// $table->timestamps(); // Sangat recommended2. Best Practices Model
â DO:
// Selalu define fillable atau guarded
protected $fillable = ['judul', 'harga'];
// Gunakan casting
protected $casts = [
'harga' => 'decimal:2',
'tanggal' => 'date',
];
// Buat accessor untuk format
public function getHargaFormatAttribute() {
return 'Rp ' . number_format($this->harga);
}
// Gunakan scope untuk query berulang
public function scopeAktif($query) {
return $query->where('status', 'aktif');
}â DON'T:
// Jangan biarkan mass assignment terbuka
protected $guarded = []; // â Dangerous!
// Jangan query di view
// @foreach(Buku::all() as $buku) // â
// Gunakan di controller/route3. Common Errors & Solutions
Error: "SQLSTATE[42S01]: Base table or view already exists"
# Solution: Table sudah ada
php artisan migrate:fresh # Drop all tablesError: "Add [field_name] to fillable property"
// Solution: Tambahkan ke $fillable
protected $fillable = ['field_name'];Error: "Class 'App\Models\Buku' not found"
# Solution: Clear cache
php artisan optimize:clear
composer dump-autoloadI. PERSIAPAN PERTEMUAN 11
Topik Pertemuan 11: Controller & View (MVC Pattern)
Preview Materi:
- Controller responsibility
- Routing advanced
- Blade templating engine
- Passing data to view
- Layout & components
Yang Perlu Disiapkan:
- Migration & Model buku dan anggota sudah jalan
- Pahami relasi Model-Database
- Data sudah ter-seed dengan baik
- Laravel project siap digunakan
Pre-reading:
- Laravel Controllers: https://laravel.com/docs/12.x/controllers (opens in a new tab)
- Blade Templates: https://laravel.com/docs/12.x/blade (opens in a new tab)
Selamat Belajar! đđ
End of Module - Pertemuan 10
Next: Pertemuan 11 - Controller & View (MVC Pattern)