setAliases(['dump-schema']) ->setDescription('Dump the schema for your database to a migration.') ->setHelp(<<%command.name% command dumps the schema for your database to a migration: %command.full_name% After dumping your schema to a migration, you can rollup your migrations using the migrations:rollup command. EOT ) ->addOption( 'formatted', null, InputOption::VALUE_NONE, 'Format the generated SQL.' ) ->addOption( 'namespace', null, InputOption::VALUE_REQUIRED, 'Namespace to use for the generated migrations (defaults to the first namespace definition).' ) ->addOption( 'filter-tables', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Filter the tables to dump via Regex.' ) ->addOption( 'line-length', null, InputOption::VALUE_OPTIONAL, 'Max line length of unformatted lines.', '120' ); } /** * @throws SchemaDumpRequiresNoMigrations */ public function execute( InputInterface $input, OutputInterface $output ): int { $formatted = $input->getOption('formatted'); $lineLength = (int) $input->getOption('line-length'); $schemaDumper = $this->getDependencyFactory()->getSchemaDumper(); if ($formatted) { if (! class_exists(SqlFormatter::class)) { throw InvalidOptionUsage::new( 'The "--formatted" option can only be used if the sql formatter is installed. Please run "composer require doctrine/sql-formatter".' ); } } $configuration = $this->getDependencyFactory()->getConfiguration(); $namespace = $input->getOption('namespace'); if ($namespace === null) { $dirs = $configuration->getMigrationDirectories(); $namespace = key($dirs); } assert(is_string($namespace)); $this->checkNoPreviousDumpExistsForNamespace($namespace); $fqcn = $this->getDependencyFactory()->getClassNameGenerator()->generateClassName($namespace); $path = $schemaDumper->dump( $fqcn, $input->getOption('filter-tables'), $formatted, $lineLength ); $this->io->text([ sprintf('Dumped your schema to a new migration class at "%s"', $path), '', sprintf( 'To run just this migration for testing purposes, you can use migrations:execute --up \'%s\'', addslashes($fqcn) ), '', sprintf( 'To revert the migration you can use migrations:execute --down \'%s\'', addslashes($fqcn) ), '', 'To use this as a rollup migration you can use the migrations:rollup command.', '', ]); return 0; } private function checkNoPreviousDumpExistsForNamespace(string $namespace): void { $migrations = $this->getDependencyFactory()->getMigrationRepository()->getMigrations(); foreach ($migrations->getItems() as $migration) { if (strpos((string) $migration->getVersion(), $namespace) !== false) { throw SchemaDumpRequiresNoMigrations::new($namespace); } } } }