Вход Регистрация
Файл: database/upgrades/2026_06_28_000020_change_comments_dates_to_datetime.php
Строк: 135
<?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
    
{
        
// Свежая схема уже создаёт created_at как datetime — конверсия не нужна
        
if (Schema::getColumnType('comments''created_at') === 'datetime') {
            return;
        }

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

        
$this->addTempColumns('comments''dateTime', ['created_at_dt''deleted_at_dt']);
        
$this->convert('comments''created_at_dt', ['created_at''deleted_at'], static fn ($r) => [
            
'created_at_dt' => $toDt($r->created_at),
            
'deleted_at_dt' => $toDt($r->deleted_at),
        ]);
        
Schema::table('comments', function (Blueprint $table) {
            
$table->dropIndex(['rating''created_at']);
            
$table->dropIndex(['created_at']);
            
$table->dropColumn(['created_at''deleted_at']);
        });
        
Schema::table('comments', function (Blueprint $table) {
            
$table->renameColumn('created_at_dt''created_at');
            
$table->renameColumn('deleted_at_dt''deleted_at');
        });
        
Schema::table('comments', function (Blueprint $table) {
            
$table->index('created_at');
            
$table->index(['rating''created_at']);
        });
    }

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

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

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