在laravel中,數(shù)據(jù)庫(kù)遷移是管理數(shù)據(jù)庫(kù)結(jié)構(gòu)變更的強(qiáng)大工具。定義表之間的關(guān)系,特別是外鍵,是數(shù)據(jù)庫(kù)設(shè)計(jì)中的關(guān)鍵一環(huán)。laravel提供了多種方式來(lái)定義外鍵,其中foreignid()輔助函數(shù)是推薦且最簡(jiǎn)潔的方式。然而,不恰當(dāng)?shù)氖褂每赡軙?huì)導(dǎo)致“duplicate column name”(重復(fù)列名)錯(cuò)誤,尤其是在執(zhí)行php artisan migrate:fresh等命令時(shí)。
當(dāng)開(kāi)發(fā)者嘗試在遷移文件中定義一個(gè)外鍵時(shí),如果同時(shí)手動(dòng)創(chuàng)建了用于外鍵的列類型(如unsignedBigInteger)又使用了foreignId()輔助函數(shù),就會(huì)出現(xiàn)重復(fù)列名錯(cuò)誤。
錯(cuò)誤示例代碼:
public function up() { Schema::enableForeignKeyConstraints(); // 通常不需要在up()方法內(nèi)手動(dòng)啟用 Schema::create('dso', function (Blueprint $table) { $table->string('id_dso',30); $table->unsignedBigInteger('id_rso'); // 第一次創(chuàng)建 'id_rso' 列 $table->foreignId('id_rso')->constrained('rso'); // foreignId() 再次嘗試創(chuàng)建 'id_rso' 列 $table->smallInteger('id_focus'); $table->smallInteger('id_wilayah'); $table->smallInteger('id_grup_wilayah'); $table->string('nama_dso',50); $table->string('created_by',50)->nullable(); $table->timestamp('created_date',$precision = 0); $table->string('modified_by',50)->nullable(); $table->timestamp('modified_date',$precision = 0)->nullable()->default(null); $table->boolean('status')->default(true); $table->timestamps(); $table->primary('id_dso'); }); }
在上述代碼中,$table->unsignedBigInteger('id_rso'); 已經(jīng)創(chuàng)建了一個(gè)名為 id_rso 的 UNSIGNED BIGINT 類型的列。緊接著,$table->foreignId('id_rso')->constrained('rso'); 會(huì)再次嘗試創(chuàng)建一個(gè)名為 id_rso 的列,并將其定義為外鍵。由于該列已存在,數(shù)據(jù)庫(kù)會(huì)拋出 SQLSTATE[42S21]: Column already exists: 1060 Duplicate column name 'id_rso' 錯(cuò)誤。
Laravel 的 foreignId() 輔助函數(shù)是一個(gè)非常方便的宏,它不僅會(huì)創(chuàng)建符合外鍵要求的列(默認(rèn)為 UNSIGNED BIGINT 類型),還會(huì)自動(dòng)將其定義為外鍵。因此,無(wú)需再手動(dòng)定義列類型。
正確用法示例:
public function up() { // Schema::enableForeignKeyConstraints(); // 通常不需要,Laravel默認(rèn)開(kāi)啟 Schema::create('dso', function (Blueprint $table) { $table->string('id_dso',30); // 直接使用 foreignId() 創(chuàng)建并定義外鍵 $table->foreignId('id_rso')->constrained('rso'); $table->smallInteger('id_focus'); $table->smallInteger('id_wilayah'); $table->smallInteger('id_grup_wilayah'); $table->string('nama_dso',50); $table->string('created_by',50)->nullable(); $table->timestamp('created_date',$precision = 0); $table->string('modified_by',50)->nullable(); $table->timestamp('modified_date',$precision = 0)->nullable()->default(null); $table->boolean('status')->default(true); $table->timestamps(); $table->primary('id_dso'); }); }
在這個(gè)修正后的代碼中,$table->foreignId('id_rso')->constrained('rso'); 這一行代碼完成了兩項(xiàng)任務(wù):
constrained() 方法是 foreignId() 的鏈?zhǔn)秸{(diào)用,用于指定外鍵引用的表。
刪除行為: 可以通過(guò) onDelete() 和 onUpdate() 方法來(lái)定義外鍵的級(jí)聯(lián)操作。
$table->foreignId('user_id')->constrained()->onDelete('cascade'); // 當(dāng)關(guān)聯(lián)用戶被刪除時(shí),級(jí)聯(lián)刪除此記錄 $table->foreignId('product_id')->constrained()->onUpdate('restrict'); // 當(dāng)關(guān)聯(lián)產(chǎn)品ID更新時(shí),限制操作
遷移順序: 定義外鍵時(shí),被引用的表(父表)必須在引用表(子表)之前創(chuàng)建。如果 rso 表的遷移文件在 dso 表之后執(zhí)行,那么在創(chuàng)建 dso 表時(shí)就會(huì)因?yàn)檎也坏?rso 表而報(bào)錯(cuò)。通常,Laravel 會(huì)根據(jù)遷移文件名的時(shí)間戳自動(dòng)排序,確保依賴關(guān)系正確。
Schema::enableForeignKeyConstraints() 與 Schema::disableForeignKeyConstraints(): 這兩個(gè)方法用于臨時(shí)啟用或禁用外鍵約束。在進(jìn)行大量數(shù)據(jù)導(dǎo)入或刪除操作時(shí),禁用外鍵可以提高性能。在 up() 方法中,通常不需要手動(dòng)調(diào)用 Schema::enableForeignKeyConstraints(),因?yàn)長(zhǎng)aravel默認(rèn)在遷移運(yùn)行時(shí)會(huì)處理好外鍵約束的啟用。只有在 down() 方法中,如果需要?jiǎng)h除帶有外鍵的表,可能需要先禁用外鍵,再刪除表,最后重新啟用。
php artisan migrate:fresh: 這個(gè)命令會(huì)刪除所有表,然后重新運(yùn)行所有遷移。這也是最容易暴露出上述重復(fù)列名錯(cuò)誤的環(huán)境,因?yàn)樗鼤?huì)從頭開(kāi)始構(gòu)建數(shù)據(jù)庫(kù)結(jié)構(gòu)。
在Laravel中定義外鍵時(shí),使用 foreignId() 輔助函數(shù)結(jié)合 constrained() 方法是最佳實(shí)踐。它不僅代碼簡(jiǎn)潔,而且能自動(dòng)處理列的創(chuàng)建和外鍵的定義,有效避免了因重復(fù)創(chuàng)建列而導(dǎo)致的“Duplicate column name”錯(cuò)誤。遵循這些最佳實(shí)踐,可以確保數(shù)據(jù)庫(kù)遷移的順暢執(zhí)行和數(shù)據(jù)庫(kù)結(jié)構(gòu)的清晰維護(hù)。
以上就是Laravel 遷移中外鍵定義與“重復(fù)列名”錯(cuò)誤的解決策略的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注php中文網(wǎng)其它相關(guān)文章!
每個(gè)人都需要一臺(tái)速度更快、更穩(wěn)定的 PC。隨著時(shí)間的推移,垃圾文件、舊注冊(cè)表數(shù)據(jù)和不必要的后臺(tái)進(jìn)程會(huì)占用資源并降低性能。幸運(yùn)的是,許多工具可以讓 Windows 保持平穩(wěn)運(yùn)行。
微信掃碼
關(guān)注PHP中文網(wǎng)服務(wù)號(hào)
QQ掃碼
加入技術(shù)交流群
Copyright 2014-2025 http://m.miracleart.cn/ All Rights Reserved | php.cn | 湘ICP備2023035733號(hào)