db->getDatabase(); // Find exact table names (handles Users/Families casing) $usersRow = $this->db->query( "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = ? AND LOWER(TABLE_NAME) = 'users' LIMIT 1", [$dbName] )->getFirstRow(); $familiesRow = $this->db->query( "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = ? AND LOWER(TABLE_NAME) = 'families' LIMIT 1", [$dbName] )->getFirstRow(); if (!$usersRow || !$familiesRow) { throw new \RuntimeException("Required tables not found: users or families in {$dbName}."); } $usersTable = $usersRow->TABLE_NAME; $familiesTable = $familiesRow->TABLE_NAME; // Make sure parents are InnoDB (required for FKs) foreach ([$usersTable, $familiesTable] as $t) { $eng = $this->db->query( "SELECT ENGINE FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=? AND TABLE_NAME=?", [$dbName, $t] )->getFirstRow(); if (!$eng || strcasecmp($eng->ENGINE ?? '', 'InnoDB') !== 0) { $this->db->query("ALTER TABLE `{$t}` ENGINE=InnoDB"); } } // Match child column types to parent id types exactly $usersIdType = $this->db->query( "SELECT COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=? AND TABLE_NAME=? AND COLUMN_NAME='id' LIMIT 1", [$dbName, $usersTable] )->getFirstRow()->COLUMN_TYPE ?? null; $familiesIdType = $this->db->query( "SELECT COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=? AND TABLE_NAME=? AND COLUMN_NAME='id' LIMIT 1", [$dbName, $familiesTable] )->getFirstRow()->COLUMN_TYPE ?? null; if (!$usersIdType || !$familiesIdType) { throw new \RuntimeException("Could not read id types from {$usersTable} / {$familiesTable}."); } // Clean slate in case a broken table exists $this->db->query("DROP TABLE IF EXISTS `family_guardians`"); // Create with perfectly matching FK column types $sql = " CREATE TABLE `family_guardians` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `family_id` {$familiesIdType} NOT NULL, `user_id` {$usersIdType} NOT NULL, `relation` VARCHAR(32) DEFAULT NULL, `is_primary` TINYINT(1) DEFAULT 0, `receive_emails` TINYINT(1) DEFAULT 1, `receive_sms` TINYINT(1) DEFAULT 0, `custody_notes` VARCHAR(255) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uq_family_user` (`family_id`,`user_id`), KEY `idx_fg_family` (`family_id`), KEY `idx_fg_user` (`user_id`), CONSTRAINT `fk_fg_family` FOREIGN KEY (`family_id`) REFERENCES `{$familiesTable}` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `fk_fg_user` FOREIGN KEY (`user_id`) REFERENCES `{$usersTable}` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; "; $this->db->query($sql); } public function down() { $this->db->query("DROP TABLE IF EXISTS `family_guardians`"); } }