forge->addField([ 'id' => [ 'type' => 'INT', 'constraint' => 11, 'unsigned' => true, 'auto_increment' => true, ], 'ip_address' => [ 'type' => 'VARCHAR', 'constraint' => '45', 'comment' => 'IP address dari percobaan login', ], 'username' => [ 'type' => 'VARCHAR', 'constraint' => '100', 'null' => true, 'comment' => 'Username yang dicoba (null jika user tidak ditemukan)', ], 'user_id' => [ 'type' => 'INT', 'constraint' => 11, 'unsigned' => true, 'null' => true, 'comment' => 'ID user jika login berhasil', ], 'success' => [ 'type' => 'TINYINT', 'constraint' => 1, 'default' => 0, 'comment' => '1 = berhasil, 0 = gagal', ], 'user_agent' => [ 'type' => 'TEXT', 'null' => true, 'comment' => 'User agent browser', ], 'created_at' => [ 'type' => 'DATETIME', 'null' => true, ], ]); $this->forge->addKey('id', true); $this->forge->addKey('ip_address'); $this->forge->addKey('username'); $this->forge->addKey('user_id'); $this->forge->addKey('created_at'); // Index composite untuk query cepat berdasarkan IP dan waktu $this->forge->addKey(['ip_address', 'created_at']); // Index composite untuk query berdasarkan username dan waktu $this->forge->addKey(['username', 'created_at']); $this->forge->createTable('login_attempts', true); } public function down() { $this->forge->dropTable('login_attempts', true); } }