setName('doctrine:database:create') ->setDescription('Creates the configured database') ->addOption('shard', 's', InputOption::VALUE_REQUIRED, 'The shard connection to use for this command') ->addOption('connection', 'c', InputOption::VALUE_OPTIONAL, 'The connection to use for this command') ->addOption('if-not-exists', null, InputOption::VALUE_NONE, 'Don\'t trigger an error, when the database already exists') ->setHelp(<<%command.name% command creates the default connections database: php %command.full_name% You can also optionally specify the name of a connection to create the database for: php %command.full_name% --connection=default EOT ); } /** * {@inheritDoc} */ protected function execute(InputInterface $input, OutputInterface $output) { $connectionName = $input->getOption('connection'); if (empty($connectionName)) { $connectionName = $this->getDoctrine()->getDefaultConnectionName(); } $connection = $this->getDoctrineConnection($connectionName); $ifNotExists = $input->getOption('if-not-exists'); $driverOptions = []; $params = $connection->getParams(); if (isset($params['driverOptions'])) { $driverOptions = $params['driverOptions']; } // Since doctrine/dbal 2.11 master has been replaced by primary if (isset($params['primary'])) { $params = $params['primary']; $params['driverOptions'] = $driverOptions; } if (isset($params['master'])) { $params = $params['master']; $params['driverOptions'] = $driverOptions; } // Cannot inject `shard` option in parent::getDoctrineConnection // cause it will try to connect to a non-existing database if (isset($params['shards'])) { $shards = $params['shards']; // Default select global $params = array_merge($params, $params['global'] ?? []); unset($params['global']['dbname'], $params['global']['path'], $params['global']['url']); if ($input->getOption('shard')) { foreach ($shards as $i => $shard) { if ($shard['id'] === (int) $input->getOption('shard')) { // Select sharded database $params = array_merge($params, $shard); unset($params['shards'][$i]['dbname'], $params['shards'][$i]['path'], $params['shards'][$i]['url'], $params['id']); break; } } } } $hasPath = isset($params['path']); $name = $hasPath ? $params['path'] : ($params['dbname'] ?? false); if (! $name) { throw new InvalidArgumentException("Connection does not contain a 'path' or 'dbname' parameter and cannot be created."); } // Need to get rid of _every_ occurrence of dbname from connection configuration and we have already extracted all relevant info from url unset($params['dbname'], $params['path'], $params['url']); $tmpConnection = DriverManager::getConnection($params); if ($tmpConnection instanceof PoolingShardConnection) { $tmpConnection->connect($input->getOption('shard')); } else { $tmpConnection->connect(); } $shouldNotCreateDatabase = $ifNotExists && in_array($name, $tmpConnection->getSchemaManager()->listDatabases()); // Only quote if we don't have a path if (! $hasPath) { $name = $tmpConnection->getDatabasePlatform()->quoteSingleIdentifier($name); } $error = false; try { if ($shouldNotCreateDatabase) { $output->writeln(sprintf('Database %s for connection named %s already exists. Skipped.', $name, $connectionName)); } else { $tmpConnection->getSchemaManager()->createDatabase($name); $output->writeln(sprintf('Created database %s for connection named %s', $name, $connectionName)); } } catch (Throwable $e) { $output->writeln(sprintf('Could not create database %s for connection named %s', $name, $connectionName)); $output->writeln(sprintf('%s', $e->getMessage())); $error = true; } $tmpConnection->close(); return $error ? 1 : 0; } }