#database #development #laravel #pattern #php

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.

 1namespace App\Domains\Common;
 2
 3use Illuminate\Support\Facades\App;
 4use Illuminate\Support\Facades\Artisan;
 5
 6trait ChecksPendingMigrations
 7{
 8    public function hasPendingMigrations(): bool
 9    {
10        if (App::environment('testing')) {
11            return false;
12        }
13
14        Artisan::call('migrate', ['--pretend' => true, '--force' => true]);
15        return trim(Artisan::output()) !== 'Nothing to migrate.';
16    }
17}

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:

 1namespace App\Console\Commands;
 2
 3use App\Domains\Common\ChecksPendingMigrations;
 4use Illuminate\Console\Command;
 5
 6final class MySampleCommand extends Command
 7{
 8    use ChecksPendingMigrations;
 9
10    protected $signature = 'my-sample-command';
11
12    protected $description = 'Sample command which checks pending migrations';
13
14    public function handle(): int
15    {
16        if ($this->hasPendingMigrations()) {
17            $this->error('Run the pending database migrations first');
18            return self::FAILURE;
19        }
20
21        return self::SUCCESS;
22    }
23}

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.