json('prices')->nullable()->after('name') ->comment('Store different duration prices and reset traffic price'); $table->boolean('sell')->default(false)->after('prices')->comment('is sell'); }); // Step 2: Migrate data to new format DB::table('v2_plan')->orderBy('id')->chunk(100, function ($plans) { foreach ($plans as $plan) { $prices = array_filter([ 'monthly' => $plan->month_price !== null ? $plan->month_price / 100 : null, 'quarterly' => $plan->quarter_price !== null ? $plan->quarter_price / 100 : null, 'half_yearly' => $plan->half_year_price !== null ? $plan->half_year_price / 100 : null, 'yearly' => $plan->year_price !== null ? $plan->year_price / 100 : null, 'two_yearly' => $plan->two_year_price !== null ? $plan->two_year_price / 100 : null, 'three_yearly' => $plan->three_year_price !== null ? $plan->three_year_price / 100 : null, 'onetime' => $plan->onetime_price !== null ? $plan->onetime_price / 100 : null, 'reset_traffic' => $plan->reset_price !== null ? $plan->reset_price / 100 : null ], function ($price) { return $price !== null; }); DB::table('v2_plan') ->where('id', $plan->id) ->update([ 'prices' => json_encode($prices), ]); } }); // Step 3: Optimize existing columns Schema::table('v2_plan', function (Blueprint $table) { // Modify existing columns to be more efficient $table->unsignedInteger('group_id')->nullable()->change(); $table->unsignedBigInteger('transfer_enable')->nullable() ->comment('Transfer limit in bytes')->change(); $table->unsignedInteger('speed_limit')->nullable() ->comment('Speed limit in Mbps, 0 for unlimited')->change(); $table->unsignedSmallInteger('reset_traffic_method')->nullable()->default(0) ->comment('重置流量方式:0跟随系统设置、1每月1号、2按月重置、3不重置、4每年1月1日、5按年重置')->change(); $table->unsignedInteger('capacity_limit')->nullable()->default(0) ->comment('0 for unlimited')->change(); }); // Step 4: Drop old columns Schema::table('v2_plan', function (Blueprint $table) { $table->dropColumn([ 'month_price', 'quarter_price', 'half_year_price', 'year_price', 'two_year_price', 'three_year_price', 'onetime_price', 'reset_price', ]); }); } /** * Reverse the migrations. */ public function down(): void { // Step 1: Add back old columns Schema::table('v2_plan', function (Blueprint $table) { $table->integer('month_price')->nullable(); $table->integer('quarter_price')->nullable(); $table->integer('half_year_price')->nullable(); $table->integer('year_price')->nullable(); $table->integer('two_year_price')->nullable(); $table->integer('three_year_price')->nullable(); $table->integer('onetime_price')->nullable(); $table->integer('reset_price')->nullable(); }); // Step 2: Restore data from new format to old format DB::table('v2_plan')->orderBy('id')->chunk(100, function ($plans) { foreach ($plans as $plan) { $prices = json_decode($plan->prices, true) ?? []; DB::table('v2_plan') ->where('id', $plan->id) ->update([ 'month_price' => $prices['monthly'] * 100 ?? null, 'quarter_price' => $prices['quarterly'] * 100 ?? null, 'half_year_price' => $prices['half_yearly'] * 100 ?? null, 'year_price' => $prices['yearly'] * 100 ?? null, 'two_year_price' => $prices['two_yearly'] * 100 ?? null, 'three_year_price' => $prices['three_yearly'] * 100 ?? null, 'onetime_price' => $prices['onetime'] * 100 ?? null, 'reset_price' => $prices['reset_traffic'] * 100 ?? null, ]); } }); // Step 3: Drop new columns Schema::table('v2_plan', function (Blueprint $table) { $table->dropColumn([ 'prices', 'sell' ]); }); // Step 4: Restore column types to original Schema::table('v2_plan', function (Blueprint $table) { $table->integer('group_id')->change(); $table->integer('transfer_enable')->change(); $table->integer('speed_limit')->nullable()->change(); $table->boolean('reset_traffic_method')->nullable()->change(); $table->integer('capacity_limit')->nullable()->change(); }); } };