diff --git a/database/migrations/2026_07_02_150000_fix_user_venue_foreign_key_to_venues.php b/database/migrations/2026_07_02_150000_fix_user_venue_foreign_key_to_venues.php new file mode 100644 index 0000000..72bbda0 --- /dev/null +++ b/database/migrations/2026_07_02_150000_fix_user_venue_foreign_key_to_venues.php @@ -0,0 +1,79 @@ + */ + private array $venueFkTables = [ + 'user_venue', + 'activities', + 'reservations', + 'blacklists', + 'venue_audit_logs', + 'ticket_grab_event_venue', + 'ticket_grab_venue_release_days', + 'verify_portal_credentials', + ]; + + public function up(): void + { + if (! Schema::hasTable('venues')) { + return; + } + + foreach ($this->venueFkTables as $table) { + $this->retargetVenueForeignKey($table); + } + } + + public function down(): void + { + // 不可逆:旧表 venues1203 可能已废弃,不回滚外键指向。 + } + + private function retargetVenueForeignKey(string $table): void + { + if (! Schema::hasTable($table) || ! Schema::hasColumn($table, 'venue_id')) { + return; + } + + $fk = DB::selectOne( + 'SELECT CONSTRAINT_NAME, REFERENCED_TABLE_NAME + FROM information_schema.KEY_COLUMN_USAGE + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = ? + AND COLUMN_NAME = ? + AND REFERENCED_TABLE_NAME IS NOT NULL + LIMIT 1', + [$table, 'venue_id'] + ); + + if (! $fk || $fk->REFERENCED_TABLE_NAME === 'venues') { + return; + } + + DB::statement( + "DELETE t FROM `{$table}` t + LEFT JOIN venues v ON v.id = t.venue_id + WHERE v.id IS NULL" + ); + + Schema::table($table, function (Blueprint $blueprint) { + $blueprint->dropForeign(['venue_id']); + }); + + Schema::table($table, function (Blueprint $blueprint) { + $blueprint->foreign('venue_id')->references('id')->on('venues')->cascadeOnDelete(); + }); + } +};