migrations/Version20251022100200.php line 1

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace DoctrineMigrations;
  4. use Doctrine\DBAL\Schema\Schema;
  5. use Doctrine\Migrations\AbstractMigration;
  6. /**
  7.  * Reorder client_id columns to be positioned directly after id column.
  8.  * Ensures consistency: id, client_id, ... other columns
  9.  */
  10. final class Version20251022100200 extends AbstractMigration
  11. {
  12.     public function getDescription(): string
  13.     {
  14.         return 'Reorder client_id columns to position 2 (after id) in all tables';
  15.     }
  16.     private function columnExists(string $tablestring $column): bool
  17.     {
  18.         $result $this->connection->fetchOne(
  19.             "SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS 
  20.              WHERE TABLE_SCHEMA = DATABASE() 
  21.              AND TABLE_NAME = ? 
  22.              AND COLUMN_NAME = ?",
  23.             [$table$column]
  24.         );
  25.         
  26.         return $result 0;
  27.     }
  28.     private function getFirstColumn(string $table): ?string
  29.     {
  30.         $result $this->connection->fetchOne(
  31.             "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS 
  32.              WHERE TABLE_SCHEMA = DATABASE() 
  33.              AND TABLE_NAME = ? 
  34.              ORDER BY ORDINAL_POSITION 
  35.              LIMIT 1",
  36.             [$table]
  37.         );
  38.         
  39.         return $result ?: null;
  40.     }
  41.     public function up(Schema $schema): void
  42.     {
  43.         // ============================================================
  44.         // Reposition client_id to be right after id column
  45.         // Using MODIFY COLUMN ... AFTER id
  46.         // ============================================================
  47.         
  48.         $tables = [
  49.             // Core entities
  50.             'person',
  51.             'provider'
  52.             'speaker',
  53.             'tags',
  54.             
  55.             // Newsletter & Communication
  56.             'newsletter',
  57.             'manual_newsletter',
  58.             'attachment',
  59.             
  60.             // Courses & Events
  61.             'course',
  62.             'course_data',
  63.             'course_field',
  64.             'course_occurrence',
  65.             'course_occurrence_time',
  66.             'course_series',
  67.             'course_subscription',
  68.             'course_subscription_booking',
  69.             'course_type',
  70.             'course_image',
  71.             'course_text',
  72.             
  73.             // Shopping & Orders
  74.             'cart',
  75.             'cart_item',
  76.             'customer_order',
  77.             'customer_order_item',
  78.             'customer_order_item_person',
  79.             'wait_item',
  80.             
  81.             // Invoicing
  82.             'invoice',
  83.             'invoice_item',
  84.             'invoice_item_attendees',
  85.             'invoice_payment',
  86.             'invoice_reminder',
  87.             
  88.             // Customer Management
  89.             'customer_document',
  90.             'customer_history_entry',
  91.             
  92.             // System & Configuration
  93.             'client_config',
  94.             'textblocks',
  95.             'protocol_entry',
  96.             'presence',
  97.             'presence_reason',
  98.             'ckimage',
  99.             'search_index_entry',
  100.             'email_history_entry',
  101.             
  102.             // Venue & Location
  103.             'venue',
  104.             'venue_room',
  105.             'venue_document',
  106.             'venue_image',
  107.             
  108.             // Speaker related
  109.             'speaker_image',
  110.             'speaker_text',
  111.             
  112.             // Categories
  113.             'category',
  114.         ];
  115.         foreach ($tables as $table) {
  116.             // Skip search_index_entry - it has a composite primary key
  117.             if ($table === 'search_index_entry') {
  118.                 // Special handling for search_index_entry: rename clientId to client_id
  119.                 if ($this->columnExists($table'clientId')) {
  120.                     $this->addSql("ALTER TABLE $table CHANGE clientId client_id INT NOT NULL FIRST");
  121.                 } elseif ($this->columnExists($table'client_id')) {
  122.                     // Already renamed, just position it first
  123.                     $this->addSql("ALTER TABLE $table MODIFY client_id INT NOT NULL FIRST");
  124.                 }
  125.                 continue;
  126.             }
  127.             
  128.             if ($this->columnExists($table'client_id')) {
  129.                 // Check if table has 'id' column
  130.                 if ($this->columnExists($table'id')) {
  131.                     // Position after 'id' column
  132.                     $this->addSql("ALTER TABLE $table MODIFY client_id INT DEFAULT NULL AFTER id");
  133.                 } else {
  134.                     // Skip tables without 'id' column
  135.                     // This shouldn't happen in our entities
  136.                 }
  137.             }
  138.         }
  139.     }
  140.     public function down(Schema $schema): void
  141.     {
  142.         // No need to reverse - column order doesn't affect functionality
  143.         // But if needed, we could reposition to original location
  144.     }
  145. }