Skip to content

Instantly share code, notes, and snippets.

@daraul
Created February 21, 2018 20:17
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save daraul/6902e56b39d49bbd762f80525f399b30 to your computer and use it in GitHub Desktop.
Save daraul/6902e56b39d49bbd762f80525f399b30 to your computer and use it in GitHub Desktop.
Laravel migrate:batch command
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
class MigrateBatch extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'migrate:batch
{--size=1 : The size of the batch (how many migrations to run in a single batch)}
{--step=1 : How many times do you want to migrate? (size=2 + step=2, will run 4 migrations in 2 batches, with 2 migrations in each}
{--refresh : Whether or not to drop the database before running. VERY DANGEROUS}
{--down : Will migrate down, instead of up}
';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Run a given number of migrations in a single batch';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
Collection::macro('select', function(Array $arguments) {
$arguments = collect($arguments);
return $this->map(function($object, $index) use ($arguments) {
$data = [];
$arguments->each(function($argument, $index) use (&$data, $object, $arguments) {
$object = (array) $object;
$data[$argument] = is_string($index) ? $object[$index] : $object[$argument];
});
return $data;
});
});
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
if($this->option('refresh')) {
$name = "Tables_in_".config('database.connections.'.config('database.default').'.database');
DB::statement('SET FOREIGN_KEY_CHECKS=0;');
collect(DB::select("SHOW TABLES"))->select([$name])->flatten()->each(function($table, $index) {
DB::table($table)->truncate();
Schema::drop($table);
});
}
if(!Schema::hasTable('migrations')) {
Artisan::call('migrate:install');
}
$table = DB::table('migrations');
$migrations = collect(array_slice(scandir(database_path('migrations')), 2))->map(function($migration, $index) {
return substr($migration, 0, -4);
});
$migrated = $table->select("migration")->get()->select(['migration'])->flatten();
$unmigrated = $migrations->diffKeys($migrated)->flatten();
$iteration = 0;
$unmigrated->chunk($this->option('size'))->each(function($chunk, $index) use ($table, $iteration) {
$batch = $table->max('batch');
$batch = is_null($batch) ? 1 : $batch + 1;
$chunk->each(function($migration, $index) use ($batch, $table, $iteration) {
$migration_path = database_path("migrations/$migration.php");
include_once $migration_path;
$class = Str::studly(substr($migration, 18));
if(class_exists($class)) {
if(!$this->option('down')) {
(new $class())->up();
$table->insert(['migration' => $migration, 'batch' => $batch]);
} else {
$this->info("Doesn't work yet. Sorry :(");
}
}
});
$iteration += 1;
return $iteration < $this->option('step');
});
}
}
@M165437
Copy link

M165437 commented May 21, 2018

I've got this ErrorException

[ErrorException]
include_once(/path/to/project/database/migrations/.git.php): failed to open stream: No such file or directory

so I added a filter

$migrations = collect(array_slice(scandir(database_path('migrations')), 2))->map(function($migration, $index) {
    return substr($migration, 0, -4);
})->filter(function ($migration) {
    return (bool) preg_match("/^[0-9]{4}_(0[1-9]|1[0-2])_(0[1-9]|[1-2][0-9]|3[0-1])/", $migration);
});

to only get migration files starting with a date.

@daraul
Copy link
Author

daraul commented Sep 26, 2018

Thanks, @M165437!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment