Laravel 4迁移问题中的外键
Posted
技术标签:
【中文标题】Laravel 4迁移问题中的外键【英文标题】:Foreign keys in Laravel 4 migrations issue 【发布时间】:2013-05-31 11:49:42 【问题描述】:我刚刚创建了一个新的 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();
);
【问题讨论】:
Laravel 4 Migrations throwing 1072 error 的可能重复项 这个问题是关于为什么上面不起作用,另一个是关于MySQL 1072错误。 刚刚进入 Laravel 并且也成功了。我的解决方法是使用单独的迁移添加外键。它有效,但感觉有点不对。 【参考方案1】:检查您的id
类型。 Laravel 4 创建一个带有 int(10) 无符号的增量 id。
如果您创建一个基本整数并尝试在其上放置一个外键,它将失败。
按照this link 文档中的建议,您应该使用$table->unsignedInteger(YOUR_ID_NAME);
创建外部ID 以使其工作。
【讨论】:
例如:(users 表)$table->increments('id');
和(posts 表)$table->unsignedInteger('user_id');
\n $table->foreign('user_id')->references('id')->on('users');
我使用了正确的类型,就像$table->integer('user_id')->unsigned();
并且在数据库中设置了 unsigned 属性,但它对我不起作用。我更新了我的代码以使用unsignedInteger
,现在一切正常
我自己也遇到过同样的问题 - Dayle Rees 已经很好地解释了它(带有示例)daylerees.com/codebright/eloquent-relationships
@alairock 很好的例子,因为我犯的一个菜鸟错误是试图在列存在之前创建外键。首先声明该列,然后将其设为外键。为此 +1!【参考方案2】:
还有一些关于这个问题的答案"General error: 1005 Can't create table" Using Laravel Schema Build and Foreign Keys
那里列出的答案摘要,包括我的:
外键一般需要 InnoDb,所以设置你的默认引擎,或者明确指定
$table->engine = 'InnoDB';
如果您的表已经创建并且默认为 MyISAM,您可能需要更改它。
外键需要引用的表存在。在创建密钥之前,请确保在较早的迁移中创建了引用的表。确保在单独的迁移中创建密钥。
外键要求数据类型一致。检查引用的字段是否为同一类型,是否有符号或无符号,长度是否相同(或更少)。
如果您在手动编码迁移和使用生成器之间切换,请确保检查您正在使用的 id 类型。 Artisan 默认使用 increments(),但 Jeffrey Way 似乎更喜欢 integer('id', true)。
【讨论】:
我的问题是它是一个以前创建的表并且默认为 MyISAM。更新被引用到 InnoDB 的表后,一切都很好。【参考方案3】:前一天有同样的问题。
问题的根源是:具有外键的列必须与该键的类型相同。 而且你有不同的类型: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 关于这个:
注意:创建引用递增整数的外键时,请记住始终使外键列无符号。
【讨论】:
【参考方案4】:它有效,但有时您只需要小心并尝试了解幕后发生的事情。
正如我在评论中所说。当你第一次运行迁移而不创建相关列时,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');
【讨论】:
那行不通。我删除了数据库,创建了一个新数据库,运行php artisan migration:install
,然后运行php artisan migrate
,错误仍然存在,但前提是我提及->foreign()
。【参考方案5】:
antonio carlos 是对的,请确保您首先创建了外键的引用表。
尝试先迁移没有外键的表,然后再进行分配外键的迁移。在这种状态下,laravel 确定引用键是存在的。并且您不必在工匠错误期间删除表格。
【讨论】:
以上是关于Laravel 4迁移问题中的外键的主要内容,如果未能解决你的问题,请参考以下文章
:完整性约束违规:1452 无法添加或更新子行:laravel 迁移中的外键约束失败
Laravel 5.2 迁移:无法添加 char 数据类型的外键