Pindah nilai column ke table rujukan (ref table) secara bulk

Kes ini melibatkan beberapa nilai column yang akan dipindahkan ke dedicated table. Contohnya table users mempunyai column negeri, pendidikan yang disimpan dengan DataType String kemudian anda inginkan negeri & pendidikan mempunyai table sendiri.

Jika anda hanya 1 column untuk dipindahkan, anda boleh merujuk Post asal Cara pindah nilai column ke table rujukan (ref table) Jika anda mempunyai banyak column teruskan membaca.

Jalankan command berikut

php artisan make:migration multiple_column_to_multiple_ref_table --table=users

Sedikit latar belakang kes ini:

  • Main table telah mempunyai column foreign key. Contoh table users mempunyai column kod_negeri (DataType asal: STRING)
  • Reference table ref_negeri direka supaya mempunyai column kod_negeri (DataType asal: STRING)
  • Sebaiknya, pastikan column pada Main table & Reference table mempunyai nama yang sama bagi mengelakkan kekeliruan

Masukkan kod berikut pada method up()

<?php

public function up()    {        
    $tables = [[                
        "main" => [                    
            'table' => 'profail',                    
            'field' => 'kod_negeriL',
        ],                
        "ref" => [                    
            'table' => 'ref_negeri',                    
            'field' => 'kod_negeri',                
        ],            ],            [                
            "main" => [                    
                'table' => 'profail',                    
                'field' => 'kod_status',                
            ],                
            "ref" => [                    
                'table' => 'ref_status',                    
                'field' => 'kod_status',                
            ],            ],                    
        ];        
        // compare value in ref table        
        foreach ($tables as $val) {                
            $mainTable = $val['main']['table'];                
            $targetMainfield = $val['main']['field'];                
            $refTable = $val['ref']['table'];                
            $targetRefField = $val['ref']['field'];                
            // ============== START compare value in tables=====================                
            $main_table = DB::table($mainTable)->distinct()->get([$targetMainfield])->pluck($targetMainfield)->toArray();                
            $ref_table = DB::table($refTable)->distinct()->get([$targetRefField])->pluck($targetRefField)->toArray();                                
            $noRef = [];                
            echo "\n====================================================\n";              
            echo "DATA NOT MATCH IN REF TABLE ".$mainTable." - ".$refTable;              
            echo "\n====================================================\n";                
            foreach ($main_table as $key => $value) {                  
                if (!in_array($value,$ref_table)) {                        
                    $noRef[] = $value;                        
                    echo $value."\n";                    
                }                
            }                
            if (count($noRef) == 0) {                  
                 echo "ALL DATA ARE MATCHES ".$mainTable." - ".$refTable."\n";                
                }                
                echo "====================================================\n";                                
                if (count($noRef) > 0) {                    
                    echo "There are data not maching in ref table ".$mainTable." - ".$refTable;                    
                    echo "\n\n\n";                    
                    die();                
                }        
            }      
             // if no confilict in ref table, execute this        
             foreach ($tables as $val) {            
                $mainTable = $val['main']['table'];            
                $targetMainfield = $val['main']['field'];            
                $refTable = $val['ref']['table'];            
                $targetRefField = $val['ref']['field'];          
                // =============== START change value string to integer ============            
                $arrData = [];            
                foreach (\DB::table($mainTable)->get()->toArray() as $data) {                
                    if (!array_key_exists($data->$targetMainfield, $arrData)) {                    
                        $kodNegeri = DB::table($refTable)->where($targetRefField, $data->$targetMainfield)->first();                    
                        $arrData[$data->$targetMainfield] = $kodNegeri->id;                    
                        echo $data->$targetMainfield." => ".$kodNegeri->id."\n";                
                    }            
                }            
                // find field and update to ref table id            
                foreach ($arrData as $arrDataName => $arrDataId) {                
                    \DB::table($mainTable)->where($targetMainfield, $arrDataName)->update([$targetMainfield => $arrDataId]);            
                }            // =============== START change colunmn type ============            
                Schema::table($mainTable, function (Blueprint $table) use ($targetMainfield, $refTable){                
                    $table->unsignedInteger($targetMainfield)->change();                
                    $table->foreign($targetMainfield)                    
                    ->references('id')->on($refTable)                    
                    ->onDelete('cascade');            
                });                
            }          
        }

Amaran: Pastikan anda telah membuat backup database

Pastikan anda menamakan entiti mengikut table & column anda dan kemudian jalankan comand berikut:

php artisan migrate

Kod diatas akan memindahkan nilai ke table baru dan menukar column foreign key DataType ke INT

memandangkan kod ini agak kompleks, jadi tiada fungsi rollback diperlukan. Pastikan anda membuat backup database sebelum membuat apa-apa perubahan

Post a Comment

Previous Post Next Post