Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Tominator's avatar

"Drop all tables" instead of "migration rollback"

Hi,

Is there a way to reset my database without rolling back all migrations? Ie do "php artisan migrate:refresh" but not rolling back, just "drop table" on all existing tables, then migrate forward?

The reason for this is that rolling back migrations is not really implemented in our firm, because a) nobody needs that really, b) you can't always fully roll back because sometimes in going forward you delete data, so it's a fake idea anyway.

I haven't found an option for what I want, is there a way?

0 likes
23 replies
bobbybouwmann's avatar

Just delete the tables in the database and migrate again?

Also I do think migrations up and down function really do add value to your application, especially when you have an application running!

Tominator's avatar

I don't want to manually delete them every time I run the test suite on the testing database, so if it could be automated (or exists somewhere as a command), that would be a lot easier :-)

joedawson's avatar

Ie do "php artisan migrate:refresh" but not rolling back, just "drop table" on all existing tables, then migrate forward?

migrate:refresh does exactly that though?

Tominator's avatar

No, it rolls back migrations:

        foreach ($migrations as $migration) {
            $this->runDown((object) ['migration' => $migration], $pretend);
        }
bashy's avatar

I alias this for a fresh migration

alias ms="php artisan migrate:reset && php artisan migrate --seed"

Queries run

bobbybouwmann's avatar

@bashy That only works if you have the down function setup for all migrations. The OP is not using that at all...

What you can do is create your own command which deletes all tables for you...

Tominator's avatar

I've no problem with the solution of creating my own command, I was just wondering if it was needed, or if someone knew of something that would be faster than me writing and debugging it :-)

bashy's avatar

I didn't see anywhere where it states there's no migrations?

Tominator's avatar

@bashy "The reason for this is that rolling back migrations is not really implemented in our firm" We have migrations, just not the down() functionality

londoh's avatar
londoh
Best Answer
Level 5

@Tominator if you didnt get it done yet, in the best traditions of Blue Peter here's one I made earlier.

I guess you could also do it via infomation_schema.

I dont know if you might need the fk checks on or not. and I think the trans isnt needed. anyway...

<?php namespace App\Console\Commands;

use DB;
use Illuminate\Console\Command;

class DropTables extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'droptables';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

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

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {

        if (!$this->confirm('CONFIRM DROP AL TABLES IN THE CURRENT DATABASE? [y|N]')) {
            exit('Drop Tables command aborted');
        }

        $colname = 'Tables_in_' . env('DB_DATABASE');

        $tables = DB::select('SHOW TABLES');

        foreach($tables as $table) {

            $droplist[] = $table->$colname;

        }
        $droplist = implode(',', $droplist);

        DB::beginTransaction();
        //turn off referential integrity
        //DB::statement('SET FOREIGN_KEY_CHECKS = 0');
        DB::statement("DROP TABLE $droplist");
        //turn referential integrity back on
        //DB::statement('SET FOREIGN_KEY_CHECKS = 1');
        DB::commit();

        $this->comment(PHP_EOL."If no errors showed up, all tables were dropped".PHP_EOL);

    }
}

regards

l.

4 likes
Tominator's avatar

Thanks, I had just finished my version :-)

Using some code I found on the internet, this is the gist of it:

    $pdo = \DB::connection($this->option('connection'))->getPdo();

    $tables = $pdo
        ->query("SHOW FULL TABLES;")
        ->fetchAll();

    $sql = 'SET FOREIGN_KEY_CHECKS=0;';

    foreach ($tables as $tableInfo) {
        // truncate tables only
        if('BASE TABLE' !== $tableInfo[1])
            continue;

        $name = $tableInfo[0];
        $sql .= 'DROP TABLE ' . $name . ';';
        $this->info('Dropping table ' . $name);
    }

    $sql .= 'SET FOREIGN_KEY_CHECKS=1;';

    $pdo->exec($sql);

However, yours is better I feel, since you don't use the specific PDO part...

1 like
Tominator's avatar

Using yours (@londoh) I tweaked it just a little bit by making it a little more flexible:

    DB::setDefaultConnection($this->option('connection'));

    $colname = 'Tables_in_' . DB::getDatabaseName();
michaeldyrynda's avatar

Why not just DROP DATABASE db_name; then CREATE DATABASE db_name;?

4 likes
Tominator's avatar

In some cases (not mine so it could work) this would also mean your mysql user needs to be given the correct access rights again.

balleyer's avatar

Why not easier:

    public function handle()
    {
        foreach(\DB::select('SHOW TABLES') as $table) {
            $table_array = get_object_vars($table);
            \Schema::drop($table_array[key($table_array)]);
        }
    }
6 likes
reinink's avatar

If you're using Postgres, you can delete all your tables like this:

$query = 'SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname=\'public\'';
$tables = array_column(DB::select($query), 'tablename');

foreach ($tables as $table) {
    DB::statement('drop table '.$table.' cascade');
}

The cascade bit in there helps get around any foreign key constraints you might have.

2 likes
BartHuis's avatar

Thanks! if you have multiple connections, you can use this:


<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use \DB;

class DropDb extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'dropdb {database}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'drops all tables of specific or all connections';

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

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        //
        $database = $this->argument('database');
        
        if($database == "all") {
            $databases = array("mysql", "connection2", "connection3");
        }
        else{
            $databases = array($database);
        }
        foreach ($databases as $databasetoempty) {
            $pdo = \DB::connection($databasetoempty)->getPdo();
    
            $tables = $pdo
                ->query("SHOW FULL TABLES;")
                ->fetchAll();
    
            $sql = 'SET FOREIGN_KEY_CHECKS=0;';
    
            foreach ($tables as $tableInfo) {
                // truncate tables only
                if ('BASE TABLE' !== $tableInfo[1])
                    continue;
        
                $name = $tableInfo[0];
                $sql .= 'DROP TABLE ' . $name . ';';
                $this->info('Dropping table ' . $name);
            }
    
            $sql .= 'SET FOREIGN_KEY_CHECKS=1;';
    
            $pdo->exec($sql);
        }
    }
}


now you can do:

php artisan dropdb all

or

php artisan dropdb connection2
nayzawoo's avatar
<?php

\Schema::dropAllTables();

:)

2 likes
isometriq's avatar

Since Laravel 5.5, there is a migrate:fresh command included.

It drops all tables and run migrations again ..see artisan help for more details.

2 likes
ken-mills's avatar

I ran into a problem with using the $column variable to access the property dynamically in the londoh best answer script above? I am running php 7.3. After doing a little more searching, I found and tested this code in the db:drop command script. Worked for me using the array_map line below.

    public function handle()
    {
        //

        if (!$this->option('force')) {
            if (!$this->confirm('CONFIRM DROP AL TABLES IN THE CURRENT DATABASE? [y|N]')) {
                exit('Drop Tables command aborted');
            }
        }

        $tables = array_map('reset', \DB::select('SHOW TABLES'));

        $droplist = implode(',', $tables);

        DB::beginTransaction();
        //turn off referential integrity
        DB::statement('SET FOREIGN_KEY_CHECKS = 0');
        DB::statement("DROP TABLE $droplist");
        //turn referential integrity back on
        DB::statement('SET FOREIGN_KEY_CHECKS = 1');
        DB::commit();

        $this->comment(PHP_EOL . "If no errors showed up, all tables were dropped" . PHP_EOL);

    }

no4ch's avatar

To drop the database use the command:

php artisan db:wipe

lehelk's avatar

@no4ch Careful with db:wipe - it wipes only the default DB on that connection. It's by design of course, but i need to drop all tables in all DBs on connection, writing my own command for this.

Please or to participate in this conversation.