Created
April 9, 2019 15:22
-
-
Save innocenzi/4484ee454897742a281e76b38e245884 to your computer and use it in GitHub Desktop.
A Symfony 4.2 command made to make fixture reloading easier. Takes into account the foreign key constraints issue.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Command; | |
use Symfony\Component\Console\Command\Command; | |
use Symfony\Component\Console\Input\ArrayInput; | |
use Symfony\Component\Console\Input\InputOption; | |
use Symfony\Component\Console\Style\SymfonyStyle; | |
use Symfony\Component\Console\Input\InputInterface; | |
use Symfony\Component\Console\Output\BufferedOutput; | |
use Symfony\Component\Console\Output\OutputInterface; | |
/** | |
* Command to delete and create the database, build its schema and loads the fixtures. | |
* | |
* @author Enzo 'Hawezo' Innocenzi <[email protected]> | |
*/ | |
class DoctrineReloadCommand extends Command | |
{ | |
const OPT_NO_FIXTURES = 'no-fixtures'; | |
const OPT_NO_DROP = 'no-drop'; | |
const OPT_NO_WARNING = 'no-warning'; | |
protected static $defaultName = 'doctrine:reload'; | |
protected function configure() | |
{ | |
$this | |
->setDescription('Delete and recreate the database, and re-build its schema right after.') | |
->addOption(self::OPT_NO_FIXTURES, 'f', InputOption::VALUE_NONE, 'Defines whether or not the fixtures have to be loaded.') | |
->addOption(self::OPT_NO_DROP, 'd', InputOption::VALUE_NONE, 'Defines whether or not the database actually has to be dropped.') | |
->addOption(self::OPT_NO_WARNING, 'w', InputOption::VALUE_NONE, 'Defines whether or not the warnings will be shown.') | |
; | |
} | |
protected function execute(InputInterface $input, OutputInterface $output) | |
{ | |
$io = new SymfonyStyle($input, $output); | |
$io->writeln(''); | |
// Loading options | |
$useFixtures = !$input->getOption(self::OPT_NO_FIXTURES); | |
$warning = !$input->getOption(self::OPT_NO_WARNING); | |
$dropDatabase = !$input->getOption(self::OPT_NO_DROP); | |
// First, drop the database | |
if ($dropDatabase) | |
{ | |
if (!$this->dropDatabase($io, $output)) { | |
return; | |
} | |
} | |
elseif ($output->isVerbose() && $warning) | |
{ | |
$io->writeln(sprintf(' <info>!</info> Not dropping database because <comment>--%s</comment> argument is passed.%s', self::OPT_NO_DROP, PHP_EOL)); | |
} | |
// Then, create it. | |
if (!$this->createDatabase($io, $output)) { | |
return; | |
} | |
// Then, drops the schema. But only if database wasn't dropped, | |
// because it's useless otherwise. | |
if (!$dropDatabase) | |
{ | |
if (!$this->dropSchema($io, $output)) { | |
return; | |
} | |
} | |
elseif ($output->isVerbose() && $warning) | |
{ | |
$io->writeln(sprintf(' <info>!</info> Not dropping schema because <comment>--%s</comment> argument is not passed.%s', self::OPT_NO_DROP, PHP_EOL)); | |
} | |
// Then, create the schema. | |
if (!$this->createSchema($io, $output)) { | |
return; | |
} | |
// Last, setup the fixtures. | |
if ($useFixtures) | |
{ | |
if (!class_exists('Doctrine\Bundle\FixturesBundle\Fixture')) { | |
if ($warning) { | |
$io->writeln(' <comment>!</comment> Not loading fixtures because the <comment>orm-fixtures</comment> bundle is not installed.'); | |
$io->writeln(sprintf(' Type <info>composer require orm-fixtures</info> to install it.%s', PHP_EOL)); | |
} | |
} | |
elseif (!$this->setupFixtures($io, $output)) | |
{ | |
return; | |
} | |
} | |
$io->success('Successfully reloaded database.'); | |
} | |
/** | |
* Drops the database if it exists. | |
* | |
* @return bool | |
*/ | |
protected function dropDatabase(SymfonyStyle $io, OutputInterface $output): bool | |
{ | |
return $this->performCommand( | |
new ArrayInput([ | |
'command' => 'doctrine:database:drop', | |
'--force' => true, | |
'--if-exists' => true | |
]), | |
$output, $io, | |
sprintf('Calling the <info>doctrine:database:drop</info> command...', self::OPT_NO_DROP), | |
'An error occured while dropping the database.' | |
); | |
} | |
/** | |
* Creates the database if it doesn't exist. | |
* | |
* @return bool | |
*/ | |
protected function createDatabase(SymfonyStyle $io, OutputInterface $output): bool | |
{ | |
return $this->performCommand( | |
new ArrayInput([ | |
'command' => 'doctrine:database:create', | |
'--no-interaction' => true, | |
'--if-not-exists' => true | |
]), | |
$output, $io, | |
sprintf('Calling the <info>doctrine:database:create</info> command...', self::OPT_NO_DROP), | |
'An error occured while creating the database.' | |
); | |
} | |
/** | |
* Drops the database schema. | |
* | |
* @return bool | |
*/ | |
protected function dropSchema(SymfonyStyle $io, OutputInterface $output): bool | |
{ | |
return $this->performCommand( | |
new ArrayInput([ | |
'command' => 'doctrine:schema:drop', | |
'--force' => true, | |
'--no-interaction' => true | |
]), | |
$output, $io, | |
sprintf('Calling the <info>doctrine:schema:drop</info> command...', self::OPT_NO_DROP), | |
'An error occured while dropping the database schema.' | |
); | |
} | |
/** | |
* Creates the database schema. | |
* | |
* @return bool | |
*/ | |
protected function createSchema(SymfonyStyle $io, OutputInterface $output): bool | |
{ | |
return $this->performCommand( | |
new ArrayInput([ | |
'command' => 'doctrine:schema:create', | |
'--no-interaction' => true | |
]), | |
$output, $io, | |
sprintf('Calling the <info>doctrine:schema:create</info> command...', self::OPT_NO_DROP), | |
'An error occured while creating the database schema..' | |
); | |
} | |
/** | |
* Sets up the fixtures. | |
* | |
* @return bool | |
*/ | |
protected function setupFixtures(SymfonyStyle $io, OutputInterface $output): bool | |
{ | |
return $this->performCommand( | |
new ArrayInput([ | |
'command' => 'doctrine:fixtures:load', | |
'--no-interaction' => true | |
]), | |
$output, $io, | |
sprintf('Calling the <info>doctrine:fixtures:load</info> command...', self::OPT_NO_DROP), | |
'An error occured while loading the fixtures.' | |
); | |
} | |
/** | |
* Performs a generic command. | |
* | |
* @param ArrayInput $input | |
* @param OutputInterface $output | |
* @param SymfonyStyle $io | |
* @param string $startMessage | |
* @param string $errorMessage | |
* | |
* @return bool | |
*/ | |
protected function performCommand(ArrayInput $input, OutputInterface $output, SymfonyStyle $io, string $startMessage = null, string $errorMessage = null): bool | |
{ | |
$application = $this->getApplication(); | |
$application->setAutoExit(false); | |
$verbosity = $output->getVerbosity(); | |
if ($verbosity >= OutputInterface::VERBOSITY_VERBOSE && null !== $startMessage) { | |
$io->writeln($startMessage); | |
} | |
$_output = $verbosity >= OutputInterface::VERBOSITY_VERBOSE ? $output : new BufferedOutput(); | |
$code = $application->run($input, $_output); | |
if (0 !== $code && null !== $errorMessage) { | |
$io->warning(sprintf('%s', $errorMessage)); | |
} | |
// New line to keep it clean if there is some debug. | |
if ($verbosity >= OutputInterface::VERBOSITY_VERBOSE) { | |
$io->writeln(''); | |
} | |
return 0 == $code; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment