Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions src/Phaseolies/Console/Commands/Migrations/DbWipeCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

namespace Phaseolies\Console\Commands\Migrations;

use Phaseolies\Console\Schedule\Command;
use Phaseolies\Console\Support\InteractsWithMigrations;
use Phaseolies\Support\Facades\DB;

class DbWipeCommand extends Command
{
use InteractsWithMigrations;

/**
* The name and signature of the console command.
*
* @var string
*/
protected $name = 'db:wipe {--connection=} {--force}';

/**
* The description of the console command.
*
* @var string
*/
protected $description = 'Drop all tables from the database';

/**
* Execute the console command.
*
* @return int
*/
public function handle(): int
{
return $this->executeWithTiming(function () {
$connection = $this->resolveConnection();

if (!$this->confirmToProceed("This will drop all tables from database connection: {$connection}", true)) {
return Command::FAILURE;
}

try {
$database = DB::connection($connection);

$database->disableForeignKeyConstraints();

try {
$dropped = $database->dropAllTables();
} finally {
$database->enableForeignKeyConstraints();
}
} catch (\Throwable $e) {
$this->displayError("Failed to wipe database [{$connection}]: {$e->getMessage()}");

return Command::FAILURE;
}

$this->displaySuccess("Dropped {$dropped} " . ($dropped === 1 ? 'table' : 'tables') . " from {$connection}");

return Command::SUCCESS;
});
}
}
43 changes: 28 additions & 15 deletions src/Phaseolies/Console/Commands/Migrations/MigrateCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,19 @@
namespace Phaseolies\Console\Commands\Migrations;

use Phaseolies\Console\Schedule\Command;
use Phaseolies\Console\Support\InteractsWithMigrations;
use Phaseolies\Database\Migration\Migrator;

class MigrateCommand extends Command
{
use InteractsWithMigrations;

/**
* The name and signature of the console command.
*
* @var string
*/
protected $name = 'migrate {--path=} {--connection=}';
protected $name = 'migrate {--path=} {--connection=} {--step} {--pretend} {--force} {--seed}';

/**
* The description of the console command.
Expand Down Expand Up @@ -45,28 +48,38 @@ public function __construct()
public function handle(): int
{
return $this->executeWithTiming(function () {
$connection = $this->option('connection') ?: config('database.default');
$connection = $this->resolveConnection();
$pretend = (bool) $this->option('pretend');

$path = $this->option('path');
if (!$this->confirmToProceed('Running migrations in production')) {
return Command::FAILURE;
}

$this->line("<fg=yellow>🔁 Running migrations on connection: {$connection}</>");
$this->line("<fg=yellow>🔁 " . ($pretend ? 'Previewing' : 'Running') . " migrations on connection: {$connection}</>");
$this->newLine();

if ($path) {
$migrations = $this->migrator->run($connection, $path);
} else {
$migrations = $this->migrator->run($connection);
try {
$migrations = $this->migrator->run($connection, $this->option('path') ?: null, [
'step' => (bool) $this->option('step'),
'pretend' => $pretend,
'progress' => $this->progressReporter(),
]);
} catch (\Throwable $e) {
$this->newLine();
$this->displayError($e->getMessage());

return Command::FAILURE;
}

if (empty($migrations)) {
$this->newLine();
$this->displayInfo('Nothing to migrate');
} else {
$this->displaySuccess('Database migrated successfully');
$this->line('<fg=yellow>📊 Migrations Executed:</>');
foreach ($migrations as $migration) {
$this->line('- <fg=white>' . $migration . '</>');
}
} elseif (!$pretend) {
$this->newLine();
$this->displaySuccess(count($migrations) . ' ' . (count($migrations) === 1 ? 'migration' : 'migrations') . ' executed');
}

if ($this->option('seed') && !$pretend) {
return $this->runSeeders();
}

return Command::SUCCESS;
Expand Down
101 changes: 101 additions & 0 deletions src/Phaseolies/Console/Commands/Migrations/MigrateFreshCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<?php

namespace Phaseolies\Console\Commands\Migrations;

use Phaseolies\Console\Schedule\Command;
use Phaseolies\Console\Support\InteractsWithMigrations;
use Phaseolies\Support\Facades\DB;
use Phaseolies\Database\Migration\Migrator;

class MigrateFreshCommand extends Command
{
use InteractsWithMigrations;

/**
* The name and signature of the console command.
*
* @var string
*/
protected $name = 'migrate:fresh {--connection=} {--seed} {--force}';

/**
* The description of the console command.
*
* @var string
*/
protected $description = 'Drop all tables and re-run all migrations for the specified or default connection';

/**
* The migrator instance.
*
* @var Migrator
*/
protected Migrator $migrator;

/**
* Create a new command instance.
*/
public function __construct()
{
parent::__construct();

$this->migrator = app('migrator');
}

/**
* Execute the console command.
*
* @return int
*/
public function handle(): int
{
return $this->executeWithTiming(function () {
$connection = $this->resolveConnection();

if (!$this->confirmToProceed("This will drop all tables from database connection: {$connection}", true)) {
return Command::FAILURE;
}

$this->line("<fg=yellow>♻️ Refreshing database on connection: {$connection}</>");

try {
$database = DB::connection($connection);

$database->disableForeignKeyConstraints();

try {
$tablesDropped = $database->dropAllTables();
} finally {
$database->enableForeignKeyConstraints();
}

$this->newLine();
$this->line("<fg=green>✔ Dropped {$tablesDropped} tables from {$connection}</>");
} catch (\Throwable $e) {
$this->displayError("Failed to refresh database [{$connection}]: {$e->getMessage()}");
return Command::FAILURE;
}

$this->newLine();
$this->line('<fg=yellow>🔁 Running migrations</>');
$this->newLine();

try {
$migrations = $this->migrator->run($connection, null, ['progress' => $this->progressReporter()]);
} catch (\Throwable $e) {
$this->newLine();
$this->displayError($e->getMessage());
return Command::FAILURE;
}

$this->newLine();
$this->displaySuccess('Database refresh completed (' . count($migrations) . ' executed)');

if ($this->option('seed')) {
return $this->runSeeders();
}

return Command::SUCCESS;
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,26 @@
namespace Phaseolies\Console\Commands\Migrations;

use Phaseolies\Console\Schedule\Command;
use Phaseolies\Support\Facades\Schema;
use Phaseolies\Support\Facades\DB;
use Phaseolies\Console\Support\InteractsWithMigrations;
use Phaseolies\Database\Migration\Migrator;

class MigrateRefreshCommand extends Command
{
use InteractsWithMigrations;

/**
* The name and signature of the console command.
*
* @var string
*/
protected $name = 'migrate:fresh {--connection=}';
protected $name = 'migrate:refresh {--connection=} {--step=} {--seed} {--force}';

/**
* The description of the console command.
*
* @var string
*/
protected $description = 'Drop all tables and re-run all migrations for the specified or default connection';
protected $description = 'Roll back all migrations (or the last --step=N) and run them again';

/**
* The migrator instance.
Expand All @@ -36,7 +37,6 @@ class MigrateRefreshCommand extends Command
public function __construct()
{
parent::__construct();

$this->migrator = app('migrator');
}

Expand All @@ -48,43 +48,49 @@ public function __construct()
public function handle(): int
{
return $this->executeWithTiming(function () {
$connection = $this->option('connection') ?: config('database.default');
$connection = $this->resolveConnection();

$this->displayWarning("This will drop all tables from database connection: <fg=white>{$connection}</>");
$this->line('Are you sure you want to proceed? (yes/no) [no]');
$response = trim(fgets(STDIN));
try {
$step = $this->integerOption('step');
} catch (\RuntimeException $e) {
$this->displayError($e->getMessage());

if (strtolower($response) !== 'yes') {
$this->displayInfo('Command cancelled');
return Command::SUCCESS;
return Command::FAILURE;
}

$this->newLine();
$this->line("<fg=yellow>♻️ Refreshing database on connection: {$connection}</>");
$scope = $step === null ? 'every migration' : "the last {$step} migration(s)";

try {
Schema::connection($connection)->disableForeignKeyConstraints();
if (!$this->confirmToProceed("This will roll back {$scope} on connection: {$connection} and run them again", true)) {
return Command::FAILURE;
}

$tablesDropped = DB::connection($connection)->dropAllTables();
$progress = $this->progressReporter();

Schema::connection($connection)->enableForeignKeyConstraints();
try {
$this->line("<fg=yellow>⏪ Rolling back on connection: {$connection}</>");
$this->newLine();

$rolledBack = $step === null
? $this->migrator->reset($connection, ['progress' => $progress])
: $this->migrator->rollback($connection, ['step' => $step, 'progress' => $progress]);

$this->newLine();
$this->line('<fg=yellow>🔁 Running migrations</>');
$this->newLine();
$this->line("<fg=green>✔ Dropped {$tablesDropped} tables from {$connection}</>");

$migrated = $this->migrator->run($connection, null, ['progress' => $progress]);
} catch (\Throwable $e) {
$this->displayError("Failed to refresh database [{$connection}]: {$e->getMessage()}");
$this->newLine();
$this->displayError($e->getMessage());

return Command::FAILURE;
}

$this->newLine();
$this->line('<fg=yellow>🔁 Running migrations</>');
$this->newLine();
$migrations = $this->migrator->run($connection);
$this->displaySuccess(sprintf('Refreshed (%d rolled back, %d executed)', count($rolledBack), count($migrated)));

$this->displaySuccess('Database refresh completed');
$this->line('<fg=yellow>📊 Migrations Executed:</>');
foreach ($migrations as $migration) {
$this->line('- <fg=white>' . $migration . '</>');
if ($this->option('seed')) {
return $this->runSeeders();
}

return Command::SUCCESS;
Expand Down
Loading
Loading