setName($this->name) ->setDescription('Executes (or dumps) the SQL needed to update the database schema to match the current mapping metadata') ->addOption('em', null, InputOption::VALUE_REQUIRED, 'Name of the entity manager to operate on') ->addOption('complete', null, InputOption::VALUE_NONE, 'This option is a no-op, is deprecated and will be removed in 4.0') ->addOption('dump-sql', null, InputOption::VALUE_NONE, 'Dumps the generated SQL statements to the screen (does not execute them).') ->addOption('force', 'f', InputOption::VALUE_NONE, 'Causes the generated SQL statements to be physically executed against your database.') ->setHelp(<<<'EOT' The %command.name% command generates the SQL needed to synchronize the database schema with the current mapping metadata of the default entity manager. For example, if you add metadata for a new column to an entity, this command would generate and output the SQL needed to add the new column to the database: %command.name% --dump-sql Alternatively, you can execute the generated queries: %command.name% --force If both options are specified, the queries are output and then executed: %command.name% --dump-sql --force Finally, be aware that this task will drop all database assets (e.g. tables, etc) that are *not* described by the current metadata. In other words, without this option, this task leaves untouched any "extra" tables that exist in the database, but which aren't described by any metadata. Hint: If you have a database with tables that should not be managed by the ORM, you can use a DBAL functionality to filter the tables and sequences down on a global level: $config->setSchemaAssetsFilter(function (string|AbstractAsset $assetName): bool { if ($assetName instanceof AbstractAsset) { $assetName = $assetName->getName(); } return !str_starts_with($assetName, 'audit_'); }); EOT); } /** * {@inheritDoc} */ protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas, SymfonyStyle $ui): int { $notificationUi = $ui->getErrorStyle(); if ($input->getOption('complete') === true) { Deprecation::trigger( 'doctrine/orm', 'https://github.com/doctrine/orm/pull/11354', 'The --complete option is a no-op, is deprecated and will be removed in Doctrine ORM 4.0.', ); $notificationUi->warning('The --complete option is a no-op, is deprecated and will be removed in Doctrine ORM 4.0.'); } $sqls = $schemaTool->getUpdateSchemaSql($metadatas); if (empty($sqls)) { $notificationUi->success('Nothing to update - your database is already in sync with the current entity metadata.'); return 0; } $dumpSql = $input->getOption('dump-sql') === true; $force = $input->getOption('force') === true; if ($dumpSql) { foreach ($sqls as $sql) { $ui->writeln(sprintf('%s;', $sql)); } } if ($force) { if ($dumpSql) { $notificationUi->newLine(); } $notificationUi->text('Updating database schema...'); $notificationUi->newLine(); $schemaTool->updateSchema($metadatas); $pluralization = count($sqls) === 1 ? 'query was' : 'queries were'; $notificationUi->text(sprintf(' %s %s executed', count($sqls), $pluralization)); $notificationUi->success('Database schema updated successfully!'); } if ($dumpSql || $force) { return 0; } $notificationUi->caution( [ 'This operation should not be executed in a production environment!', '', 'Use the incremental update to detect changes during development and use', 'the SQL DDL provided to manually update your database in production.', ], ); $notificationUi->text( [ sprintf('The Schema-Tool would execute "%s" queries to update the database.', count($sqls)), '', 'Please run the operation by passing one - or both - of the following options:', '', sprintf(' %s --force to execute the command', $this->getName()), sprintf(' %s --dump-sql to dump the SQL statements to the screen', $this->getName()), ], ); return 1; } }