Stephan Salley
Stephan Salley

Reputation: 31

Laravel exclude table from dropping

I have a large table which consists of millions of rows. I wanted to know how I could exclude this table from being dropped by php artisan migrate:fresh.

I'd really appreciate it if you could help me out!

Upvotes: 1

Views: 1987

Answers (2)

Sean Burlington
Sean Burlington

Reputation: 930

The answer is in the comments but I think is worth spelling out.

use php artisan:fresh instead of refresh

refresh calls dropAllTables() so avoid this if you want to keep anything

fresh runs all rollbacks and then all migrations

This has the side benefit of testing rollbacks (at least that they run).

You can then exclude the large table from migrations and manage it elsewhere.

It is also possible to put the large table as an early migration and only run migrations after this point

eg only refresh the last 5 migrations

php artisan migrate:refresh --step=5

https://laravel.com/docs/9.x/migrations

You may also want to run tests without dropping all tables.

By default Laravel runs migrate:fresh on every test run but this can be avoided by having a base TestCase like this


<?php

namespace Tests;

use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\RefreshDatabaseState;
use Illuminate\Contracts\Console\Kernel;

abstract class TestCase extends BaseTestCase
{
    use CreatesApplication;
    use RefreshDatabase;



    /**
     * Override the standard method and use refresh instead of fresh
     *
     */
    protected function refreshTestDatabase()
    {
        if (! RefreshDatabaseState::$migrated) {
            $this->artisan('migrate:refresh', ['--seed' => true]);
            $this->app[Kernel::class]->setArtisan(null);
            RefreshDatabaseState::$migrated = true;
        }

        $this->beginDatabaseTransaction();
    }

}

See the API docs for how RefreshDatabase works

https://github.com/laravel/framework/blob/9.x/src/Illuminate/Foundation/Testing/RefreshDatabase.php#L70

Upvotes: 0

Giles Bennett
Giles Bennett

Reputation: 1636

When you ask Laravel to create a new migration, the file it creates has two methods :

public function up()

which is what is executed when the migration is run, and

public function down()

which is what is executed when the migration is rolled back (either using the rollback command, or the refresh command).

By default, all that the down() method contains when the file is created is a step to drop the table :

public function down()
{
    Schema::dropIfExists('table_name_here');
}

So in theory, if you wanted to, you could prevent your table from being dropped by removing that line from the migration.

The problem, though, is that using the "refresh" command means that it will rollback all migrations, and then run the migration again - at this point, if you've still got the up() function, the migration will fall over because it's trying to create a table that's already there (because it hasn't been removed).

So, I think your options are twofold :

  1. Remove the table from the migrations completely (and remove any reference to it in the migrations table in the database) to prevent it being affected by migrations going on around it.

  2. If it has to be handled through migrations (perhaps it has keys pointing to / from it to other tables) then I would export the content of the table as a raw SQL dump, save it in a file on your system, and then leave the migrations along - still have it being created / destroyed by the migration process, but use the "-- seed" option to put all the data back in it after a migration is run.

Upvotes: 1

Related Questions