Sistem Informasi Perpustakaan CodeIgniter 4: Setup dan Konfigurasi Database

By | Oktober 17, 2026
CRUD kategori buku CodeIgniter 4
This entry is part 2 of 2 in the series Sistem Informasi Perpustakaan CodeIgniter 4

MWI – Halo sobat pembelajar pada web MuSa. Tutorial CodeIgniter 4 perpustakaan merupakan langkah awal yang sangat baik bagi Anda yang ingin menguasai pengembangan aplikasi web modern dengan pola Model-View-Controller. Melalui seri pertama ini, Anda akan mempelajari persiapan lingkungan kerja, konfigurasi database MySQL, serta pembuatan struktur tabel menggunakan fitur migration dan seeder.

Mengenal Aplikasi SIPUS dan Keunggulannya

Aplikasi Sistem Informasi Perpustakaan Sekolah (SIPUS) dirancang untuk mengelola data koleksi buku, anggota, serta transaksi peminjaman secara terstruktur. Penggunaan framework CodeIgniter 4 memberikan performa yang cepat, struktur kode yang rapi, serta tingkat keamanan bawaan yang sangat andal.

Di samping itu, Anda juga akan memanfaatkan kerangka kerja Bootstrap 5 untuk membangun antarmuka pengguna yang responsif. Untuk mempelajari dasar-dasar sintaks dan fitur framework ini secara lebih mendalam, Anda dapat mengunjungi dokumentasi resmi CodeIgniter 4.

Instalasi dan Konfigurasi Framework CodeIgniter 4

Langkah pertama, buka terminal atau command prompt pada komputer Anda. Jalankan perintah composer berikut untuk mengunduh framework CodeIgniter 4 ke dalam folder htdocs atau www:

composer create-project codeigniter4/appstarter sipus

Setelah proses pengunduhan selesai, buka folder proyek sipus menggunakan editor kode pilihan Anda. Selanjutnya, ubah nama berkas env menjadi .env lalu atur konfigurasi database MySQL seperti berikut:

CI_ENVIRONMENT = development

database.default.hostname = localhost
database.default.database = sipus_db
database.default.username = root
database.default.password =
database.default.DBDriver = MySQLi
database.default.port = 3306

Membuat DB dan Migration Tabel Database

Langkah kedua, Kita perlu mempersiapkan database terdahulu dengan perintah

php spark db:create sipus_db

Lanjutkan dengan membuat struktur tabel database menggunakan fitur migration agar perubahan skema data terorganisasi dengan baik. Jalankan perintah CLI berikut untuk membuat berkas migration:

php spark make:migration CreateSipusTables

Buka berkas migration yang baru terbentuk di folder app/Database/Migrations, lalu tambahkan skema pembuatan tabel users, categories, books, dan members. 2026-10-16-000001_CreateSipusTables.php — membuat tujuh tabel beserta relasi.

<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class CreateSipusTables extends Migration
{
    public function up()
    {
        // 1. USERS
        $this->forge->addField([
            'id' => ['type' => 'INT', 'unsigned' => true, 'auto_increment' => true],
            'name' => ['type' => 'VARCHAR', 'constraint' => 100],
            'email' => ['type' => 'VARCHAR', 'constraint' => 150],
            'password_hash' => ['type' => 'VARCHAR', 'constraint' => 255],
            'role' => ['type' => 'VARCHAR', 'constraint' => 20, 'default' => 'petugas'],
            'is_active' => ['type' => 'TINYINT', 'constraint' => 1, 'unsigned' => true, 'default' => 1],
            'created_at' => ['type' => 'DATETIME', 'null' => true],
            'updated_at' => ['type' => 'DATETIME', 'null' => true],
        ]);
        $this->forge->addKey('id', true);
        $this->forge->addUniqueKey('email');
        $this->forge->createTable('users', true, ['ENGINE' => 'InnoDB']);

        // 2. CATEGORIES
        $this->forge->addField([
            'id' => ['type' => 'INT', 'unsigned' => true, 'auto_increment' => true],
            'name' => ['type' => 'VARCHAR', 'constraint' => 100],
            'description' => ['type' => 'TEXT', 'null' => true],
            'created_at' => ['type' => 'DATETIME', 'null' => true],
            'updated_at' => ['type' => 'DATETIME', 'null' => true],
        ]);
        $this->forge->addKey('id', true);
        $this->forge->addUniqueKey('name');
        $this->forge->createTable('categories', true, ['ENGINE' => 'InnoDB']);

        // 3. BOOKS
        $this->forge->addField([
            'id' => ['type' => 'INT', 'unsigned' => true, 'auto_increment' => true],
            'category_id' => ['type' => 'INT', 'unsigned' => true],
            'code' => ['type' => 'VARCHAR', 'constraint' => 30],
            'title' => ['type' => 'VARCHAR', 'constraint' => 200],
            'author' => ['type' => 'VARCHAR', 'constraint' => 150],
            'publisher' => ['type' => 'VARCHAR', 'constraint' => 150, 'null' => true],
            'published_year' => ['type' => 'YEAR', 'null' => true],
            'stock_total' => ['type' => 'INT', 'unsigned' => true, 'default' => 0],
            'stock_available' => ['type' => 'INT', 'unsigned' => true, 'default' => 0],
            'is_active' => ['type' => 'TINYINT', 'constraint' => 1, 'unsigned' => true, 'default' => 1],
            'created_at' => ['type' => 'DATETIME', 'null' => true],
            'updated_at' => ['type' => 'DATETIME', 'null' => true],
        ]);
        $this->forge->addKey('id', true);
        $this->forge->addUniqueKey('code');
        $this->forge->addKey('category_id');
        $this->forge->addForeignKey('category_id', 'categories', 'id', 'CASCADE', 'RESTRICT');
        $this->forge->createTable('books', true, ['ENGINE' => 'InnoDB']);

        // 4. MEMBERS
        $this->forge->addField([
            'id' => ['type' => 'INT', 'unsigned' => true, 'auto_increment' => true],
            'member_code' => ['type' => 'VARCHAR', 'constraint' => 30],
            'name' => ['type' => 'VARCHAR', 'constraint' => 150],
            'class_name' => ['type' => 'VARCHAR', 'constraint' => 50, 'null' => true],
            'phone' => ['type' => 'VARCHAR', 'constraint' => 30, 'null' => true],
            'status' => ['type' => 'VARCHAR', 'constraint' => 20, 'default' => 'active'],
            'created_at' => ['type' => 'DATETIME', 'null' => true],
            'updated_at' => ['type' => 'DATETIME', 'null' => true],
        ]);
        $this->forge->addKey('id', true);
        $this->forge->addUniqueKey('member_code');
        $this->forge->addKey('status');
        $this->forge->createTable('members', true, ['ENGINE' => 'InnoDB']);

        // 5. LOANS
        $this->forge->addField([
            'id' => ['type' => 'INT', 'unsigned' => true, 'auto_increment' => true],
            'loan_code' => ['type' => 'VARCHAR', 'constraint' => 30],
            'member_id' => ['type' => 'INT', 'unsigned' => true],
            'user_id' => ['type' => 'INT', 'unsigned' => true],
            'loan_date' => ['type' => 'DATE'],
            'due_date' => ['type' => 'DATE'],
            'status' => ['type' => 'VARCHAR', 'constraint' => 20, 'default' => 'active'],
            'notes' => ['type' => 'TEXT', 'null' => true],
            'created_at' => ['type' => 'DATETIME', 'null' => true],
            'updated_at' => ['type' => 'DATETIME', 'null' => true],
        ]);
        $this->forge->addKey('id', true);
        $this->forge->addUniqueKey('loan_code');
        $this->forge->addKey('member_id');
        $this->forge->addKey('user_id');
        $this->forge->addKey('status');
        $this->forge->addForeignKey('member_id', 'members', 'id', 'CASCADE', 'RESTRICT');
        $this->forge->addForeignKey('user_id', 'users', 'id', 'CASCADE', 'RESTRICT');
        $this->forge->createTable('loans', true, ['ENGINE' => 'InnoDB']);

        // 6. LOAN_DETAILS
        $this->forge->addField([
            'id' => ['type' => 'INT', 'unsigned' => true, 'auto_increment' => true],
            'loan_id' => ['type' => 'INT', 'unsigned' => true],
            'book_id' => ['type' => 'INT', 'unsigned' => true],
            'quantity' => ['type' => 'INT', 'unsigned' => true, 'default' => 1],
            'created_at' => ['type' => 'DATETIME', 'null' => true],
            'updated_at' => ['type' => 'DATETIME', 'null' => true],
        ]);
        $this->forge->addKey('id', true);
        $this->forge->addUniqueKey(['loan_id', 'book_id']);
        $this->forge->addKey('book_id');
        $this->forge->addForeignKey('loan_id', 'loans', 'id', 'CASCADE', 'RESTRICT');
        $this->forge->addForeignKey('book_id', 'books', 'id', 'CASCADE', 'RESTRICT');
        $this->forge->createTable('loan_details', true, ['ENGINE' => 'InnoDB']);

        // 7. LOAN_RETURNS
        // Satu detail peminjaman dapat dikembalikan beberapa kali (partial return).
        $this->forge->addField([
            'id' => ['type' => 'INT', 'unsigned' => true, 'auto_increment' => true],
            'loan_detail_id' => ['type' => 'INT', 'unsigned' => true],
            'user_id' => ['type' => 'INT', 'unsigned' => true],
            'quantity' => ['type' => 'INT', 'unsigned' => true],
            'returned_at' => ['type' => 'DATETIME'],
            'notes' => ['type' => 'TEXT', 'null' => true],
            'created_at' => ['type' => 'DATETIME', 'null' => true],
        ]);
        $this->forge->addKey('id', true);
        $this->forge->addKey('loan_detail_id');
        $this->forge->addKey('user_id');
        $this->forge->addForeignKey('loan_detail_id', 'loan_details', 'id', 'CASCADE', 'RESTRICT');
        $this->forge->addForeignKey('user_id', 'users', 'id', 'CASCADE', 'RESTRICT');
        $this->forge->createTable('loan_returns', true, ['ENGINE' => 'InnoDB']);
    }

    public function down()
    {
        // Drop dari tabel anak ke tabel induk karena terdapat foreign key.
        $this->db->disableForeignKeyChecks();

        $this->forge->dropTable('loan_returns', true);
        $this->forge->dropTable('loan_details', true);
        $this->forge->dropTable('loans', true);
        $this->forge->dropTable('members', true);
        $this->forge->dropTable('books', true);
        $this->forge->dropTable('categories', true);
        $this->forge->dropTable('users', true);

        $this->db->enableForeignKeyChecks();
    }
}

Eksekusi perintah php spark migrate pada terminal untuk menerapkan skema tersebut ke dalam database MySQL Anda.

php spark migrate
php spark migrate:status

Mengisi Data Awal Menggunakan Seeder

Langkah ketiga, buatlah berkas seeder untuk mengisikan akun pengguna awal serta data kategori bawaan menggunakan perintah berikut:

php spark make:seeder SipusSeeder

SipusSeeder.php — menyiapkan akun admin, kategori, buku, dan anggota contoh.

<?php

namespace App\Database\Seeds;

use CodeIgniter\Database\Seeder;
use RuntimeException;

class SipusSeeder extends Seeder
{
    public function run()
    {
        // Password wajib ditentukan di .env agar tidak ada password default tersembunyi.
        $adminPassword = env('SIPUS_ADMIN_PASSWORD');

        if (! is_string(adminPassword)||strlen(adminPassword) < 12) {
            throw new RuntimeException(
                'Atur SIPUS_ADMIN_PASSWORD di .env (minimal 12 karakter) sebelum menjalankan seeder.'
            );
        }

        $users = $this->db->table('users');
        $adminEmail = 'admin@sipus.local';

        if (! $users->where('email', $adminEmail)->get()->getRowArray()) {
            $users->insert([
                'name'          => 'Administrator SIPUS',
                'email'         => $adminEmail,
                'password_hash' => password_hash($adminPassword, PASSWORD_DEFAULT),
                'role'          => 'admin',
                'is_active'     => 1,
                'created_at'    => date('Y-m-d H:i:s'),
            ]);
        }

        $categories = [
            ['name' => 'Fiksi', 'description' => 'Novel, cerpen, dan karya fiksi.'],
            ['name' => 'Pendidikan', 'description' => 'Buku pelajaran dan materi pembelajaran.'],
            ['name' => 'Sains', 'description' => 'Ilmu pengetahuan alam dan teknologi.'],
        ];

        foreach ($categories as $category) {
            $exists = $this->db->table('categories')
                ->where('name', $category['name'])
                ->get()->getRowArray();

            if (! $exists) {
                this->db->table('categories')->insert(category);
            }
        }

        $categoryRows = $this->db->table('categories')->get()->getResultArray();
        $categoryIds = [];
        foreach ($categoryRows as $category) {
            categoryIds[category['name']] = $category['id'];
        }

        $books = [
            [
                'category_id' => $categoryIds['Fiksi'],
                'code' => 'BK-0001',
                'title' => 'Laskar Pelangi',
                'author' => 'Andrea Hirata',
                'publisher' => 'Bentang Pustaka',
                'published_year' => 2005,
                'stock_total' => 4,
                'stock_available' => 4,
                'is_active' => 1,
            ],
            [
                'category_id' => $categoryIds['Pendidikan'],
                'code' => 'BK-0002',
                'title' => 'Matematika SMA',
                'author' => 'Tim Penyusun',
                'publisher' => 'Penerbit Contoh',
                'published_year' => 2024,
                'stock_total' => 5,
                'stock_available' => 5,
                'is_active' => 1,
            ],
            [
                'category_id' => $categoryIds['Sains'],
                'code' => 'BK-0003',
                'title' => 'Pengantar Ilmu Sains',
                'author' => 'Tim Penyusun',
                'publisher' => 'Penerbit Contoh',
                'published_year' => 2023,
                'stock_total' => 3,
                'stock_available' => 3,
                'is_active' => 1,
            ],
        ];

        foreach ($books as $book) {
            $exists = $this->db->table('books')
                ->where('code', $book['code'])
                ->get()->getRowArray();

            if (! $exists) {
                $book['created_at'] = date('Y-m-d H:i:s');
                this->db->table('books')->insert(book);
            }
        }

        $members = [
            [
                'member_code' => 'AG-0001',
                'name' => 'Andi Pratama',
                'class_name' => 'X-1',
                'phone' => '081200000001',
                'status' => 'active',
            ],
            [
                'member_code' => 'AG-0002',
                'name' => 'Siti Rahma',
                'class_name' => 'X-2',
                'phone' => '081200000002',
                'status' => 'active',
            ],
            [
                'member_code' => 'AG-0003',
                'name' => 'Budi Santoso',
                'class_name' => 'XI-1',
                'phone' => '081200000003',
                'status' => 'inactive',
            ],
        ];

        foreach ($members as $member) {
            $exists = $this->db->table('members')
                ->where('member_code', $member['member_code'])
                ->get()->getRowArray();

            if (! $exists) {
                $member['created_at'] = date('Y-m-d H:i:s');
                this->db->table('members')->insert(member);
            }
        }
    }
}

Jalankan perintah php spark db:seed UserSeeder untuk memasukkan data awal ke dalam database.

php spark db:seed SipusSeeder

Akhirnya, persiapan awal tutorial CodeIgniter 4 perpustakaan telah selesai dan siap dilanjutkan ke tahap pembuatan master data pada artikel berikutnya. (ms)

Sistem Informasi Perpustakaan CodeIgniter 4

Sistem Informasi Perpustakaan CodeIgniter 4: Rancangan Aplikasi SIPUS

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *

Situs ini menggunakan Akismet untuk mengurangi spam. Pelajari bagaimana data komentar Anda diproses