Php Laravel迁移自引用外键问题

Php Laravel迁移自引用外键问题,php,mysql,foreign-keys,migration,laravel,Php,Mysql,Foreign Keys,Migration,Laravel,您好,我在使用迁移架构生成器创建表时遇到问题。 具有自引用外键的表出现问题。 以下是产生错误的代码: Schema::create('cb_category', function($table) { $table->integer('id')->primary()->unique()->unsigned(); $table->integer('domain_id')->unsigned();

您好,我在使用迁移架构生成器创建表时遇到问题。 具有自引用外键的表出现问题。 以下是产生错误的代码:

        Schema::create('cb_category', function($table)
    {
        $table->integer('id')->primary()->unique()->unsigned();
        $table->integer('domain_id')->unsigned();
        $table->foreign('domain_id')->references('id')->on('cb_domain'); 
        $table->integer('parent_id')->nullable(); 
        $table->foreign('parent_id')->references('id')->on('cb_category')->onUpdate('cascade')->onDelete('cascade'); 
        $table->string('name');
        $table->integer('level');
    });
以下是错误:

  SQLSTATE[HY000]: General error: 1005 Can't create table 'eklik2.#sql-7d4_e' (errno: 150) (SQL: alter table `cb_cate
gory
添加约束cb\u category\u parent\u id\u外键(
parent\u id
)引用del上的cb\u category
id`) ete在更新级联时级联)(绑定:数组( ))

[例外情况] SQLSTATE[HY000]:一般错误:1005无法创建表“eklik2.#sql-7d4_e”(错误号:150)


有什么想法吗?

您必须将其分成两个模式块,一个创建列,另一个添加FK。mysql不能同时做这两件事。

我可能来不及参加聚会了,但官方文件声称,如果是整数,外键必须是
->unsigned()

注意:当创建一个引用递增 整数,请记住始终使外键列无符号

另外,如果您(正如我一样)拼错了
unsigned()
,Artisan也不会失败,我花了好几个小时试图弄清楚为什么没有创建密钥

所以有两件事: 1.在整数递增的情况下,始终使外键列无符号 2.检查
unsigned()的拼写

试试这两个查询:

Schema::create('cb_category', function($table)
{
    $table->integer('id')->primary()->unique()->unsigned();
    $table->integer('parent_id')->nullable();  
});

Schema::table('cb_category', function (Blueprint $table) 
{
    $table->foreign('parent_id')->references('id')->on('cb_category')->onUpdate('cascade')->onDelete('cascade');
});

我认为您有另一个表,它引用了您要创建的当前表。 我遇到了这个问题,并移除了那张表,我的问题就解决了

Laravel 8 Laravel还支持创建外键约束,用于在数据库级别强制实现引用完整性。例如,让我们在posts表中定义一个用户id列,该列引用用户表中的id列:

Schema::table('posts', function (Blueprint $table) {
    $table->unsignedBigInteger('user_id');

    $table->foreign('user_id')->references('id')->on('users');
});
由于这种语法相当冗长,Laravel提供了其他更简洁的方法,这些方法使用约定来提供更好的开发人员体验。上面的例子可以这样写:

Schema::table('posts', function (Blueprint $table) {
    $table->foreignId('user_id')->constrained();
});
foreignd
方法是
unsignedbiginger
的别名,而约束方法将使用约定来确定引用的表和列名。如果表名与约定不匹配,可以通过将表名作为参数传递给
constrated
方法来指定表名:

Schema::table('posts', function (Blueprint $table) {
    $table->foreignId('user_id')->constrained('users');
});
您还可以为约束的
“on delete”
“on update”
属性指定所需的操作:

$table->foreignId('user_id')
      ->constrained()
      ->onDelete('cascade');
必须在
约束
之前调用任何附加命令:

$table->foreignId('user_id')
      ->nullable()
      ->constrained();
要删除外键,可以使用
dropForeign
方法,将要删除的外键约束作为参数传递。基于表名和约束中的列,外键约束使用与索引相同的命名约定,后跟
“\u Foreign”
后缀:

$table->dropForeign('posts_user_id_foreign');
或者,您可以将包含保存外键的列名的数组传递给
dropForeign
方法。数组将使用Laravel的模式生成器使用的约束名称约定自动转换:

$table->dropForeign(['user_id']);
您可以使用以下方法在迁移中启用或禁用外键约束:

Schema::enableForeignKeyConstraints();

Schema::disableForeignKeyConstraints();
默认情况下,SQLite禁用外键约束。使用SQLite时,在迁移中尝试创建外键之前,请确保在数据库配置中启用外键支持。此外,SQLite仅在创建表时支持外键,而在更改表时不支持外键


也是一种迟来的反应,但可能是一种更为惯用的方式,用于Laravel 8

使用App\Models\CbCategory;
...
模式::创建(“cb_类别”,函数(Blueprint$表)
{
$table->id();
$table->ForeigndFor(CbCategory::class,“父id”)
->级联更新()
->级联删除()
->可空();
});
请注意:我在这里猜到了
CbCategory
的类名。使用类引用第一手资料(而不是以前的表名字符串)可以让静态代码检查器在将来的类名更改中进行检查。
此外,
父id
列名处的
\u id
-后缀也很重要


愿以下资源能满足您的求知欲:

  • id()
  • foreigndfor()
  • cascadeOnDelete()
    &
    cascadeOnUpdate()

我把它分成了两条语句,但错误仍然存在:Schema::create(…);Schema::table('cb_category',function($table){$table->foreign('parent_id')->references('id')->on('cb_category')->onUpdate('cascade')->onDelete('cascade');};用断裂来解决。代码如下:Schema::create('cb_category',function($table){…})$dbh=DB::getPdo()$dbh->query(“ALTER TABLE cb_category ADD CONSTRAINT fk_cb_category\u parent_id外键(parent_id)在删除时引用cb_category(id)在更新时不执行任何操作”);这与问题中的问题相同。无法使表在创建时引用自身,因为在创建表时不存在要引用的表,这并不能回答问题。另外,这只是文件的复制+粘贴,每个人都可以自己阅读。这似乎是正确的答案。工作很好,很有意义。
Schema::enableForeignKeyConstraints();

Schema::disableForeignKeyConstraints();