Search code examples
phplaravellaravel-artisanlaravel-migrationslaravel-10

Proper way to access migrations files building custom refresh/seed in Laravel


Looking for a smarter way to do this. I have 4 migrations files (out of MANY dozen) that are related. I also have a seeder for these. Doing php artisan migrate:fresh --seed takes a good 30-45 seconds each time (there are also a few dozen seeders) and I want to just drop my 4 tables and rebuild quickly while testing.

I want to define this programmatically instead of with a CLI, so I made an artisan command:

/* routes/console.php */
Artisan::command('refresh-my-tables', function() {
    $numbers = include __DIR__ . './../database/migrations/2023_05_03_175125_create_my_table_numbers_table.php';
    $files = include __DIR__ . './../database/migrations/2023_05_08_160034_create_my_table_files_table.php';
    $orders = include __DIR__ . './../database/migrations/2023_05_03_175124_create_my_table_orders_table.php';
    $parent = include __DIR__ . './../database/migrations/2023_05_03_171245_create_my_table_table.php';

    // These are ordered intentionally to deal with foreign key constraints
    $numbers->down();
    $files->down();
    $orders->down();
    $parent->down();
    $parent->up();
    $orders->up();
    $files->up();
    $numbers->up();

    (new Database\Seeders\MyTableSeeder)->run();
});

Just need a simple php artisan refresh-my-tables

This feels... wrong. Specifically the include [long absolute filename]. I had thought Laravel, in the past, had a way to hook into migrations by name (letting PSR-4 handle finding the classes), but now, php artisan make:migration builds a file that returns an anonymous Migration extended class.

All Google and SO searches just refer to artisan migrate without acknowledging more complex edge-cases that, I can imagine, are quite common for sufficiently large projects. Is this the best (most Laravel-flavored) way to do this?


Solution

  • The old way of doing things is still valid at the time of this writing and Laravel 10. You can refactor your anonymous classes to look like this instead:

    use Illuminate\Support\Facades\Schema;
    use Illuminate\Database\Schema\Blueprint;
    use Illuminate\Database\Migrations\Migration;
    
    class CreateUsersTable extends Migration
    {
        public function up()
        {
            Schema::create('users', function (Blueprint $table) {
                ...
            }
        }
        public function down()
        {
            Schema::dropIfExists('users');
        }
    }
    

    Then your calls would just instantiate that class and run its methods.

    EDIT: If you are coming to this from the internet and this isn't working, be sure to also add the path to these migrations to your composer.json so the autoload knows it's there. "autoload":{..."classmap": ["database/migrations/"]}