'integer', 'biginteger' => 'bigInteger', 'string' => 'string', 'text' => 'text', 'boolean' => 'boolean', 'datetime' => 'datetime', 'timestamp' => 'timestamp', 'date' => 'date', 'time' => 'time', 'decimal' => 'decimal', 'float' => 'float', 'binary' => 'binary', 'json' => 'json' ]; public function __construct(?string $migrationsPath = null) { $this->migrationsPath = $migrationsPath ?: getcwd() . '/database/migrations'; } /** * Generate migration file based on table definition */ public function generateMigration(string $tableName, array $fields = [], string $action = 'create', ?SymfonyStyle $io = null): bool { try { // Ensure migrations directory exists if (!is_dir($this->migrationsPath)) { if (!mkdir($this->migrationsPath, 0755, true)) { if ($io) { $io->error("无法创建迁移目录: {$this->migrationsPath}"); } return false; } } // Generate migration name and class name $migrationName = $this->generateMigrationName($tableName, $action); $className = $this->generateClassName($migrationName); // Generate timestamp $timestamp = date('YmdHis'); $filename = $timestamp . '_' . $migrationName . '.php'; $filePath = $this->migrationsPath . '/' . $filename; // Generate migration content $content = $this->generateMigrationContent($className, $tableName, $fields, $action); // Write migration file if (file_put_contents($filePath, $content) !== false) { if ($io) { $io->success("Migration created: {$filename}"); } return true; } else { if ($io) { $io->error("无法写入迁移文件: {$filename}"); } return false; } } catch (\Exception $e) { if ($io) { $io->error('生成迁移文件时发生错误: ' . $e->getMessage()); } return false; } } /** * Generate migration name */ private function generateMigrationName(string $tableName, string $action): string { switch ($action) { case 'create': return 'create_' . $tableName . '_table'; case 'add_column': return 'add_columns_to_' . $tableName . '_table'; case 'drop_column': return 'drop_columns_from_' . $tableName . '_table'; case 'modify': return 'modify_' . $tableName . '_table'; default: return 'update_' . $tableName . '_table'; } } /** * Generate migration class name */ private function generateClassName(string $migrationName): string { return Util::mapFileNameToClassName($migrationName); } /** * Generate migration file content */ private function generateMigrationContent(string $className, string $tableName, array $fields, string $action): string { $content = "generateCreateTableContent($tableName, $fields); break; case 'add_column': $content .= $this->generateAddColumnContent($tableName, $fields); break; case 'drop_column': $content .= $this->generateDropColumnContent($tableName, $fields); break; default: $content .= $this->generateModifyTableContent($tableName, $fields); break; } $content .= " }\n"; $content .= "}\n"; return $content; } /** * Generate create table content */ private function generateCreateTableContent(string $tableName, array $fields): string { $content = " \$table = \$this->table('{$tableName}');\n"; if (!empty($fields)) { foreach ($fields as $field) { $fieldName = $field['name']; $fieldType = $this->fieldTypes[$field['type']] ?? 'string'; $options = $this->buildFieldOptions($field); $content .= " \$table->addColumn('{$fieldName}', '{$fieldType}'"; if (!empty($options)) { $content .= ", " . $this->arrayToString($options); } $content .= ");\n"; } } // Add indexes if specified foreach ($fields as $field) { if (!empty($field['index'])) { $content .= " \$table->addIndex(['{$field['name']}']);\n"; } if (!empty($field['unique'])) { $content .= " \$table->addIndex(['{$field['name']}'], ['unique' => true]);\n"; } } $content .= " \$table->create();\n"; return $content; } /** * Generate add column content */ private function generateAddColumnContent(string $tableName, array $fields): string { $content = " \$table = \$this->table('{$tableName}');\n"; foreach ($fields as $field) { $fieldName = $field['name']; $fieldType = $this->fieldTypes[$field['type']] ?? 'string'; $options = $this->buildFieldOptions($field); $content .= " \$table->addColumn('{$fieldName}', '{$fieldType}'"; if (!empty($options)) { $content .= ", " . $this->arrayToString($options); } $content .= ");\n"; } $content .= " \$table->update();\n"; return $content; } /** * Generate drop column content */ private function generateDropColumnContent(string $tableName, array $fields): string { $content = " \$table = \$this->table('{$tableName}');\n"; foreach ($fields as $field) { $fieldName = is_array($field) ? $field['name'] : $field; $content .= " \$table->removeColumn('{$fieldName}');\n"; } $content .= " \$table->update();\n"; return $content; } /** * Generate modify table content */ private function generateModifyTableContent(string $tableName, array $fields): string { $content = " \$table = \$this->table('{$tableName}');\n"; $content .= " // Add your table modifications here\n"; $content .= " \$table->update();\n"; return $content; } /** * Build field options array */ private function buildFieldOptions(array $field): array { $options = []; if (isset($field['length'])) { $options['limit'] = (int)$field['length']; } if (isset($field['null'])) { $options['null'] = (bool)$field['null']; } else { $options['null'] = true; // Default to nullable } if (isset($field['default'])) { $options['default'] = $field['default']; } if (isset($field['comment'])) { $options['comment'] = $field['comment']; } if (isset($field['after'])) { $options['after'] = $field['after']; } // Handle precision and scale for decimal fields if ($field['type'] === 'decimal') { if (isset($field['precision'])) { $options['precision'] = (int)$field['precision']; } if (isset($field['scale'])) { $options['scale'] = (int)$field['scale']; } } return $options; } /** * Convert array to string representation */ private function arrayToString(array $array): string { $parts = []; foreach ($array as $key => $value) { if (is_string($value)) { $parts[] = "'{$key}' => '{$value}'"; } elseif (is_bool($value)) { $parts[] = "'{$key}' => " . ($value ? 'true' : 'false'); } elseif (is_null($value)) { $parts[] = "'{$key}' => null"; } else { $parts[] = "'{$key}' => {$value}"; } } return '[' . implode(', ', $parts) . ']'; } /** * Get supported field types */ public function getSupportedFieldTypes(): array { return array_keys($this->fieldTypes); } /** * Set migrations path */ public function setMigrationsPath(string $path): void { $this->migrationsPath = $path; } /** * Get migrations path */ public function getMigrationsPath(): string { return $this->migrationsPath; } }