我刚刚创建了一个新的Laravel 4项目,我发现架构生成器的外键方面发生了奇怪的事情。如果我在任何迁移中使用->foreign()
方法,我会抛出MySQL错误150和一般错误1005.根据laravel.com/docs的文档,底部的两个场景应该有效吗?有谁知道他们为什么不这样做?
以下工作正常:
Schema::create('areas', function($table)
{
$table->engine ='InnoDB';
$table->increments('id');
$table->integer('region_id')->references('id')->on('regions');
$table->string('name', 160);
$table->timestamps();
});
但这两个不起作用:
Schema::create('areas', function($table)
{
$table->engine ='InnoDB';
$table->increments('id');
$table->foreign('region_id')->references('id')->on('regions');
$table->string('name', 160);
$table->timestamps();
});
Schema::create('areas', function($table)
{
$table->engine ='InnoDB';
$table->increments('id');
$table->integer('region_id');
$table->foreign('region_id')->references('id')->on('regions');
$table->string('name', 160);
$table->timestamps();
});
答案 0 :(得分:53)
检查您的id
类型。 Laravel 4使用int(10)unsigned创建一个增量id。
如果您创建一个基本整数并尝试在其上放置一个外键,它将失败。
正如this link文档中所建议的那样,您应该使用$table->unsignedInteger(YOUR_ID_NAME);
创建外部ID以使其正常工作。
答案 1 :(得分:7)
此问题还有一些答案"General error: 1005 Can't create table" Using Laravel Schema Build and Foreign Keys
其中列出的答案摘要,包括我的答案:
外键通常需要InnoDb,因此请设置默认引擎,或明确指定
$table->engine = 'InnoDB';
如果您的表已经创建并默认为MyISAM,您可能需要更改它。
外键需要引用的表存在。在创建密钥之前,请确保在先前的迁移中创建了引用的表。考虑在单独的迁移中创建密钥以确保。
外键要求数据类型一致。检查引用的字段是否是相同的类型,无论是有符号还是无符号,它的长度是否相同(或更小)。
如果要在手动编码迁移和使用生成器之间切换,请确保检查正在使用的ID类型。 Artisan默认使用 incrementments(),但Jeffrey Way似乎更喜欢整数('id',true)。
答案 2 :(得分:5)
前一天有同样的问题。
问题的根源是:带有外键的列必须与该键的类型相同。 你有不同的类型: INT / UNSIGNED INT
这使得ID成为UNSIGNED INT
$table->increments('id');
这使得region_id成为INT
$table->integer('region_id')->references('id')->on('regions');
要解决此问题,请将region_id设为UNSIGNED INT
$table->integer('region_id')->unsigned()->references('id')->on('regions');
^^^^^^^^^ note here
Laravel的文档mention有关于此的内容:
注意:创建引用递增整数的外键时,请记住始终使外键列无符号。
答案 3 :(得分:2)
它有效,但有时候你必须要小心,并试着了解幕后发生的事情。
正如我在评论中所说。当您第一次运行迁移而不创建相关列时,Laravel迁移服务会创建您的表,然后,当您尝试再次迁移时,它将始终显示错误,表明该表已存在。
因此,您只需drop table areas
并再次运行php artisan migrate
即可解决所有问题。
编辑:
我刚刚在这里创建了你的迁移(下面)并且它有效。
正如您所看到的,我没有使用MySQL,因此它必定是MySQL的问题。检查MySQL外键文档,看看您的元数据是否符合InnoDB要求:http://dev.mysql.com/doc/refman/5.6/en/innodb-foreign-key-constraints.html。
<?php
use Illuminate\Database\Migrations\Migration;
class CreateAreasTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('regions', function($table)
{
// $table->engine = 'InnoDB';
$table->increments('id');
$table->string('name', 160)->unique();
$table->timestamps();
});
Schema::create('areas', function($table)
{
// $table->engine ='InnoDB';
$table->increments('id');
$table->integer('region_id');
$table->foreign('region_id')->references('id')->on('regions');
$table->string('name', 160);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('areas');
Schema::drop('regions');
}
}
答案 4 :(得分:1)
antonio carlos是对的,请确保您首先创建了外键的参考表。
尝试首先迁移没有外键的表,然后进行另一次迁移,分配外键。在这种状态下,laravel确定引用键是存在的。你不必在工匠错误中丢桌。