DatabaseSyncCommand.php 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. <?php
  2. namespace PhpDevCommunity\PaperORM\Command;
  3. use PhpDevCommunity\Console\Command\CommandInterface;
  4. use PhpDevCommunity\Console\InputInterface;
  5. use PhpDevCommunity\Console\Option\CommandOption;
  6. use PhpDevCommunity\Console\Output\ConsoleOutput;
  7. use PhpDevCommunity\Console\OutputInterface;
  8. use PhpDevCommunity\PaperORM\Migration\PaperMigration;
  9. use PhpDevCommunity\PaperORM\Tools\EntityExplorer;
  10. class DatabaseSyncCommand implements CommandInterface
  11. {
  12. private PaperMigration $paperMigration;
  13. private ?string $env;
  14. private string $entityDir;
  15. /**
  16. * @param PaperMigration $paperMigration
  17. * @param string $entityDir
  18. * @param string|null $env
  19. */
  20. public function __construct(PaperMigration $paperMigration, string $entityDir, ?string $env = null)
  21. {
  22. $this->paperMigration = $paperMigration;
  23. $this->env = $env;
  24. $this->entityDir = $entityDir;
  25. }
  26. public function getName(): string
  27. {
  28. return 'paper:database:sync';
  29. }
  30. public function getDescription(): string
  31. {
  32. return 'Update the SQL database structure so it matches the current ORM entities.';
  33. }
  34. public function getOptions(): array
  35. {
  36. return [
  37. new CommandOption('no-execute', 'n', 'Show the generated SQL statements without executing them.', true)
  38. ];
  39. }
  40. public function getArguments(): array
  41. {
  42. return [];
  43. }
  44. public function execute(InputInterface $input, OutputInterface $output): void
  45. {
  46. $io = ConsoleOutput::create($output);
  47. if (!$this->isEnabled()) {
  48. throw new \LogicException('This command is only available in `dev` environment.');
  49. }
  50. $noExecute = $input->getOptionValue('no-execute');
  51. $platform = $this->paperMigration->getEntityManager()->getPlatform();
  52. $io->title('Starting database sync on ' . $platform->getDatabaseName());
  53. $io->list([
  54. 'Database : ' . $platform->getDatabaseName(),
  55. 'Entities directory : ' . $this->entityDir
  56. ]);
  57. $entities = EntityExplorer::getEntities([$this->entityDir]);
  58. $io->title('Number of entities detected: ' . count($entities));
  59. $io->listKeyValues($entities);
  60. $updates = $this->paperMigration->getSqlDiffFromEntities($entities);
  61. if (empty($updates)) {
  62. $io->info('No differences detected — all entities are already in sync with the database schema.');
  63. return;
  64. }
  65. $count = count($updates);
  66. $io->writeln("📘 Database synchronization plan");
  67. $io->writeln("{$count} SQL statements will be executed:");
  68. $io->writeln("");
  69. $io->numberedList($updates);
  70. if ($noExecute) {
  71. $io->info('Preview mode only — SQL statements were displayed but NOT executed.');
  72. return;
  73. }
  74. $io->writeln("");
  75. $io->writeln("🚀 Applying changes to database...");
  76. $conn = $this->paperMigration->getEntityManager()->getConnection();
  77. foreach ($updates as $sql) {
  78. $conn->executeStatement($sql);
  79. $io->writeln("✔ Executed: {$sql}");
  80. }
  81. $io->success("Database successfully synchronized.");
  82. }
  83. private function isEnabled(): bool
  84. {
  85. return 'dev' === $this->env || 'test' === $this->env;
  86. }
  87. }