forge->addField([ 'id' => ['type' => 'INT', 'unsigned' => true, 'auto_increment' => true], 'type' => ['type' => 'ENUM("classroom","book","office","kitchen")', 'null' => false, 'default' => 'office'], 'name' => ['type' => 'VARCHAR', 'constraint' => 120, 'null' => false], '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(['type', 'name']); // unique per type $this->forge->createTable('inventory_categories', true, [ 'ENGINE' => 'InnoDB', ]); // --------- inventory_items ---------- $this->forge->addField([ 'id' => ['type' => 'INT', 'unsigned' => true, 'auto_increment' => true], 'type' => ['type' => 'ENUM("classroom","book","office","kitchen")', 'null' => false], 'category_id' => ['type' => 'INT', 'unsigned' => true, 'null' => true], 'name' => ['type' => 'VARCHAR', 'constraint' => 190, 'null' => false], 'description' => ['type' => 'TEXT', 'null' => true], 'quantity' => ['type' => 'INT', 'unsigned' => true, 'default' => 0], 'unit' => ['type' => 'VARCHAR', 'constraint' => 32, 'null' => true, 'default' => null], // Classroom-only condition 'condition' => ['type' => 'ENUM("good","needs_repair","need_replace","cannot_find")', 'null' => true, 'default' => null], // Book extras (author removed earlier) 'isbn' => ['type' => 'VARCHAR', 'constraint' => 32, 'null' => true], 'edition' => ['type' => 'VARCHAR', 'constraint' => 32, 'null' => true], // Misc 'sku' => ['type' => 'VARCHAR', 'constraint' => 64, 'null' => true], 'notes' => ['type' => 'TEXT', 'null' => true], // Academic tagging 'semester' => ['type' => 'ENUM("Spring","Fall")', 'null' => true], 'school_year' => ['type' => 'VARCHAR', 'constraint' => 16, 'null' => true], // e.g. 2025-2026 // Audit 'updated_by' => ['type' => 'INT', 'unsigned' => true, 'null' => true], 'created_at' => ['type' => 'DATETIME', 'null' => true], 'updated_at' => ['type' => 'DATETIME', 'null' => true], ]); // Indexes $this->forge->addKey('id', true); $this->forge->addKey(['type', 'name']); $this->forge->addKey(['school_year', 'semester']); $this->forge->addKey('category_id'); // ensure indexed for FK $this->forge->addKey('updated_by'); // ensure indexed for FK // Category FK (safe; category table we just created with InnoDB) $this->forge->addForeignKey('category_id', 'inventory_categories', 'id', 'SET NULL', 'CASCADE'); // Create items table first, then add users FK conditionally $this->forge->createTable('inventory_items', true, [ 'ENGINE' => 'InnoDB', ]); // ---- Add updated_by → users(id) FK conditionally & safely ---- $db = \Config\Database::connect(); if ($db->tableExists('users')) { // Confirm users is InnoDB and id is an unsigned INT $engineRow = $db->query(" SELECT ENGINE FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'users' ")->getFirstRow('array'); $colRow = $db->query(" SELECT COLUMN_TYPE, IS_NULLABLE FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'users' AND COLUMN_NAME = 'id' ")->getFirstRow('array'); $isInno = isset($engineRow['ENGINE']) && strtoupper($engineRow['ENGINE']) === 'INNODB'; $isUint = isset($colRow['COLUMN_TYPE']) && stripos($colRow['COLUMN_TYPE'], 'int') !== false && stripos($colRow['COLUMN_TYPE'], 'unsigned') !== false; if ($isInno && $isUint) { // Add the FK now (separate ALTER avoids "incorrectly formed" during CREATE) $db->query(" ALTER TABLE inventory_items ADD CONSTRAINT fk_inventory_items_updated_by FOREIGN KEY (updated_by) REFERENCES users(id) ON DELETE SET NULL ON UPDATE CASCADE "); } // If not compatible, we skip the FK to avoid migration failure. } } public function down() { // Drop children first $db = \Config\Database::connect(); if ($db->tableExists('inventory_items')) { // drop conditional FK if exists try { $db->query("ALTER TABLE inventory_items DROP FOREIGN KEY fk_inventory_items_updated_by"); } catch (\Throwable $e) {} } $this->forge->dropTable('inventory_items', true); $this->forge->dropTable('inventory_categories', true); } }