Skip to content

Instantly share code, notes, and snippets.

@innocenzi
Created April 9, 2019 15:22
Show Gist options
  • Save innocenzi/4484ee454897742a281e76b38e245884 to your computer and use it in GitHub Desktop.
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.
<?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