I often create custom commands to do things like data migrations.
Once scenario that pops up quite often is that I want to check that all database migrations are applied before doing the data migration.
To make this easier from within a console command, I started with creating a trait which can check this.
The basic idea is to run artisan migrate
with the --pretend
option and checking the output.
namespace App\Domains\Common; use Illuminate\Support\Facades\App;use Illuminate\Support\Facades\Artisan; trait ChecksPendingMigrations{ public function hasPendingMigrations(): bool { if (App::environment('testing')) { return false; } Artisan::call('migrate', ['--pretend' => true, '--force' => true]); return trim(Artisan::output()) !== 'Nothing to migrate.'; }}
Note that when running tests, I'm skipping the check as the migrations are already applied anyway.
Using it inside a custom command is then very easy and can by done by using the trait and calling the hasPendingMigrations
function:
namespace App\Console\Commands; use App\Domains\Common\ChecksPendingMigrations;use Illuminate\Console\Command; final class MySampleCommand extends Command{ use ChecksPendingMigrations; protected $signature = 'my-sample-command'; protected $description = 'Sample command which checks pending migrations'; public function handle(): int { if ($this->hasPendingMigrations()) { $this->error('Run the pending database migrations first'); return self::FAILURE; } return self::SUCCESS; }}
A different approach can be to simply apply the migrations instead of checking them. If prefer no to do this as I want to be able to check what is happening.