Вход Регистрация
Файл: database/upgrades/2026_06_28_000032_change_mailings_dates_to_datetime.php
Строк: 124
<?php

use IlluminateDatabaseMigrationsMigration;
use 
IlluminateDatabaseSchemaBlueprint;
use 
IlluminateSupportFacadesDate;
use 
IlluminateSupportFacadesDB;
use 
IlluminateSupportFacadesSchema;

return new class extends 
Migration {
    
/**
     * Чанковая конверсия с транзакцией на чанк: createFromTimestamp/parse сохраняют
     * историческую таймзону (старый DST), а батч-коммит убирает fsync-на-строку.
     * whereNull по $resumeCol позволяет продолжить с места падения (таймаут на шареде).
     */
    
private function convert(string $tablestring $resumeCol, array $cols, callable $map): void
    
{
        
DB::table($table)->select(array_merge(['id'], $cols))
            ->
whereNull($resumeCol)
            ->
orderBy('id')
            ->
chunkById(5000, function ($rows) use ($table$map) {
                
DB::transaction(function () use ($rows$table$map) {
                    foreach (
$rows as $row) {
                        
DB::table($table)->where('id'$row->id)->update($map($row));
                    }
                });
            });
    }

    
/**
     * Создаёт только отсутствующие временные колонки: упавший upgrade мог
     * оставить их с прошлого запуска, повторный запуск не должен падать.
     */
    
private function addTempColumns(string $tablestring $type, array $cols): void
    
{
        
$missing array_filter($cols, static fn ($col) => ! Schema::hasColumn($table$col));

        if (
$missing) {
            
Schema::table($table, static function (Blueprint $blueprint) use ($type$missing) {
                foreach (
$missing as $col) {
                    
$blueprint->{$type}($col)->nullable();
                }
            });
        }
    }

    public function 
up(): void
    
{
        
// Свежая схема уже создаёт колонки как datetime — конверсия не нужна
        
if (Schema::getColumnType('mailings''created_at') === 'datetime') {
            return;
        }

        
$toDt = static fn ($v) => $v Date::createFromTimestamp($vconfig('app.timezone'))->format('Y-m-d H:i:s') : null;

        
$this->addTempColumns('mailings''dateTime', ['created_at_dt''sent_at_dt']);
        
$this->convert('mailings''created_at_dt', ['created_at''sent_at'], static fn ($r) => [
            
'created_at_dt' => $toDt($r->created_at),
            
'sent_at_dt'    => $toDt($r->sent_at),
        ]);
        
Schema::table('mailings', function (Blueprint $table) {
            
$table->dropColumn(['created_at''sent_at']);
        });
        
Schema::table('mailings', function (Blueprint $table) {
            
$table->renameColumn('created_at_dt''created_at');
            
$table->renameColumn('sent_at_dt''sent_at');
        });
    }

    public function 
down(): void
    
{
        
// Колонка уже int — откатывать нечего
        
if (Schema::getColumnType('mailings''created_at') !== 'datetime') {
            return;
        }

        
$toInt = static fn ($v) => $v Date::parse($vconfig('app.timezone'))->getTimestamp() : null;

        
$this->addTempColumns('mailings''integer', ['created_at_int''sent_at_int']);
        
$this->convert('mailings''created_at_int', ['created_at''sent_at'], static fn ($r) => [
            
'created_at_int' => $toInt($r->created_at),
            
'sent_at_int'    => $toInt($r->sent_at),
        ]);
        
Schema::table('mailings', function (Blueprint $table) {
            
$table->dropColumn(['created_at''sent_at']);
        });
        
Schema::table('mailings', function (Blueprint $table) {
            
$table->renameColumn('created_at_int''created_at');
            
$table->renameColumn('sent_at_int''sent_at');
        });
    }
};
Онлайн: 1
Реклама