一条命令快速搞定 Laravel 的数据库重置操作

说明

我们在日常开发中时常会遇到各种 migration 执行报错的问题,大部分情况下都是本地数据库的数据出现了问题。这个时候我们通常会通过以下 3 个步骤来对这个问题进行修复:

  1. 删除本地所有数据库表
  2. 重新执行 migration
  3. 重新运行 db:seed

如果每次都得将上面几个步骤手动操作一遍的话相信你也会崩溃的。因此我借助 Laravel 提供的自定义命令行功能把上面几个步骤简化为一个命令来快速修复这种问题。

$ php artisan project:reset

命令行创建

下面跟大家说下如何将此命令快速添加到 Laravel 项目中。

第一步你需要先创建一个 ProjectResetCommand 文件,不知道如何创建的可看 @Summer 写的 Laravel 5.1 Artisan 命令行实战

第二步则是将以下内容写入到 ProjectResetCommand 文件中。

app/Console/Commands/ProjectResetCommand.php:

<?php namespace App\Console\Commands;

use Illuminate\Console\Command;
use DB;
use App;

class ProjectResetCommand extends Command
{
    protected $signature = 'project:reset {--force : enforce}';

    protected $description = "Reset database";

    public function __construct()
    {
        parent::__construct();
    }

    public function handle()
    {
        // 防呆操作
        $this->productionCheckHint();

        // fixing db:seed class not found
        $this->execShellWithPrettyPrint('composer dump');

        $this->info("Will delete all tables, and run the 'migrate' and 'db:seed' commands");

        $this->nukeDatabase();

        // 生成数据库迁移,同时数据填充
        $this->call('migrate', [
            '--seed'  => 'yes',
            '--force' => 'yes'
        ]);
    }

    // 清洗数据库
    public function nukeDatabase()
    {
        $colname = 'Tables_in_' . env('DB_DATABASE');

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

        foreach ($tables as $table) {
            $droplist[] = $table->$colname;
            $this->info('Will delete table - ' . $table->$colname);
        }
        if (!isset($droplist)) {
            $this->error('No table');
            return;
        }
        $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("All the tables have been deleted".PHP_EOL);
    }

    // 执行命令行并区块化打印结果
    public function execShellWithPrettyPrint($command)
    {
        $this->info('---');
        $this->info($command);
        $output = shell_exec($command);
        $this->info($output);
        $this->info('---');
    }

    // 高危动作,生产环境下的防呆保护
    public function productionCheckHint($message = '')
    {
        $message = $message ?: 'This is a "very dangerous" operation';
        if (App::environment('production')
            && !$this->option('force')
            && !$this->confirm('Your are in「Production」environment, '.$message.'! Are you sure you want to do this? [y|N]')
        ) {
            exit('Command termination');
        }
    }
}

最后在 Kernel.php 文件中添加 ProjectResetCommand:

    protected $commands = [
        Commands\Inspire::class,
        Commands\ProjectResetCommand::class,
    ];

至此,命令已可正常运行,Have fun!:sparkles: :sparkles: :sparkles:

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 2
Summer

description 不对

7年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!