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