You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 8执行migrate:fresh时迁移失败,请求排查外键约束问题

Laravel迁移外键约束错误解决

问题描述

学习《Laravel 8 From Scratch》第54集时,执行php artisan migrate:fresh --seed触发外键约束错误,无法创建posts表,提示外键引用的categories表不存在。

错误日志:

lance@lance-vivobook:~/laravel-blog$ php artisan migrate:fresh

  Dropping all tables ............................................. 38ms DONE

   INFO  Preparing database.  

  Creating migration table ......................................... 8ms DONE

   INFO  Running migrations.  

  2014_10_12_000000_create_users_table ............................ 32ms DONE
  2014_10_12_100000_create_password_reset_tokens_table ............ 19ms DONE
  2019_08_19_000000_create_failed_jobs_table ...................... 17ms DONE
  2019_12_14_000001_create_personal_access_tokens_table ........... 28ms DONE
  2023_07_14_080115_create_posts_table ............................ 40ms FAIL

   Illuminate\Database\QueryException 

  SQLSTATE[HY000]: General error: 1005 Can't create table `blog`.`posts` (errno: 150 "Foreign key constraint is incorrectly formed") (Connection: mysql, SQL: alter table `posts` add constraint `posts_category_id_foreign` foreign key (`category_id`) references `categories` (`id`) on delete cascade)

  at vendor/laravel/framework/src/Illuminate/Database/Connection.php:795
    791▕         // If an exception occurs when attempting to run a query, we'll format the error
    792▕         // message to include the bindings with SQL, which will make this exception a
    793▕         // lot more helpful to the developer instead of just the database's errors.
    794▕         catch (Exception $e) {
  ➜ 795▕             throw new QueryException(
    796▕                 $this->getName(), $query, $this->prepareBindings($bindings), $e
    797▕             );
    798▕         }
    799▕     }

      +9 vendor frames 

  10  database/migrations/2023_07_14_080115_create_posts_table.php:24
      Illuminate\Support\Facades\Facade::__callStatic()
      +35 vendor frames 

  46  artisan:37
      Illuminate\Foundation\Console\Kernel::handle()

核心原因

Laravel迁移按文件名的时间戳顺序执行,create_categories_table.php的时间戳晚于create_posts_table.php,导致创建posts表时,categories表还未被创建,数据库无法识别外键关联的目标表,因此抛出约束错误。

解决方案

调整迁移文件顺序

修改create_categories_table.php的文件名时间戳,确保它早于create_posts_table.php的时间戳。例如:

  • 原posts迁移文件名:2023_07_14_080115_create_posts_table.php
  • 修改后categories迁移文件名:2023_07_14_080000_create_categories_table.php

修改后重新执行迁移命令:

php artisan migrate:fresh --seed

额外验证

确保categories表的id字段类型与posts表的category_id字段类型一致(两者均为unsignedBigInteger,代码中已通过$table->id()和$table->foreignId()实现,无需额外修改)。

相关代码参考

create_posts_table.php

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->constrained()->cascadeOnDelete();
            $table->foreignId('category_id')->constrained()->cascadeOnDelete();
            $table->string('slug')->unique();
            $table->string('title');
            $table->text('excerpt');
            $table->text('body');
            $table->timestamps();
            $table->timestamp('published_at')->nullable();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('posts');
    }
};

create_categories_table.php

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('categories', function (Blueprint $table) {
            $table->id();
            $table->string('name')->unique();
            $table->string('slug')->unique();
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('categories');
    }
};

内容的提问来源于stack exchange,提问作者lance2k

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 18:04:52