Laravel 8.X Eloquent 中数据库迁移的正确外键约束语法是什么?
What is the correct foreign key constraint syntax for a database migration in Laravel 8.X Eloquent?
我是 Laravel 和 Eloquent 菜鸟。
我正在尝试在“清单项目”table 中做一个简单的外键,它将来自“用户”table 的主 ID 作为外键。
这是我的两个数据库迁移:
用户:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
项目:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateItemsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('items', function (Blueprint $table) {
$table->id();
$table->integer('user_id')->unsigned();
$table->string('itemName');
$table->string('itemDescription');
$table->timestamps();
});
Schema::table('items', function($table) {
$table->foreign('user_id')->references('id')->on('users');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('items');
}
}
尝试 运行 php artisan migrate
会产生以下错误:
Migrating: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_000000_create_users_table (0.49 seconds)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated: 2014_10_12_100000_create_password_resets_table (0.59 seconds)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated: 2019_08_19_000000_create_failed_jobs_table (0.33 seconds)
Migrating: 2021_05_04_085648_create_items_table
Illuminate\Database\QueryException
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL: alter table `items` add constraint `items_user_id_foreign` foreign key (`user_id`) references `users` (`id`))
at D:\Applications\laragon\www\ToDoApp\vendor\laravel\framework\src\Illuminate\Database\Connection.php:671
667| // If an exception occurs when attempting to run a query, we'll format the error
668| // message to include the bindings with SQL, which will make this exception a
669| // lot more helpful to the developer instead of just the database's errors.
670| catch (Exception $e) {
> 671| throw new QueryException(
672| $query, $this->prepareBindings($bindings), $e
673| );
674| }
675|
1 D:\Applications\laragon\www\ToDoApp\vendor\laravel\framework\src\Illuminate\Database\Connection.php:464
PDOException::("SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint")
2 D:\Applications\laragon\www\ToDoApp\vendor\laravel\framework\src\Illuminate\Database\Connection.php:464
PDOStatement::execute()
应该注意的是,我可以直接在 PHPMyAdmin GUI 中实现我需要的东西,或者使用基本的 PHP PDO,但我不明白 Eloquent 和需要了解我做错了什么。
我感觉这与两次 table 迁移之间的属性定义不匹配有关,但我尝试的一些事情导致了交替错误。
用以下代码替换您的 items
迁移:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateItemsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('items', function (Blueprint $table) {
$table->id();
$table->integer('user_id')->unsigned();
$table->string('itemName');
$table->string('itemDescription');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('items');
}
}
列的类型和符号必须相同(有符号或无符号)
$table->integer('user_id')->unsigned();
应该是 $table->bigInteger('user_id')->unsigned();
只需为外键 (docs) 制作一个新的迁移文件。像
php artisan make:migration add_columns_to_items_table
为什么对同一个 table 使用不同的文件?因为我们在设置 foreignKey 之前先设置了 table 对吗? :)
然后在 up() 函数的迁移文件中:
Schema::table('items', function (Blueprint $table) {
$table->foreignId('user_id')->constrained();
});
是的,它更短更好用于开发目的
当您在 one-to-many
关系的 one
部分之前为 many
创建迁移时,会发生这种情况。在您的情况下,我猜您在 users
之前为 items
创建了迁移。只需根据您的关系重命名您的迁移文件。另请注意,您的关系列必须属于同一类型。在您的情况下,您引用的是 4 字节的 integer
到 8 字节的 bigInteger
。 (id
列是一个 unsigned
8 字节整数)。
我是 Laravel 和 Eloquent 菜鸟。
我正在尝试在“清单项目”table 中做一个简单的外键,它将来自“用户”table 的主 ID 作为外键。
这是我的两个数据库迁移:
用户:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
项目:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateItemsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('items', function (Blueprint $table) {
$table->id();
$table->integer('user_id')->unsigned();
$table->string('itemName');
$table->string('itemDescription');
$table->timestamps();
});
Schema::table('items', function($table) {
$table->foreign('user_id')->references('id')->on('users');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('items');
}
}
尝试 运行 php artisan migrate
会产生以下错误:
Migrating: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_000000_create_users_table (0.49 seconds)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated: 2014_10_12_100000_create_password_resets_table (0.59 seconds)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated: 2019_08_19_000000_create_failed_jobs_table (0.33 seconds)
Migrating: 2021_05_04_085648_create_items_table
Illuminate\Database\QueryException
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL: alter table `items` add constraint `items_user_id_foreign` foreign key (`user_id`) references `users` (`id`))
at D:\Applications\laragon\www\ToDoApp\vendor\laravel\framework\src\Illuminate\Database\Connection.php:671
667| // If an exception occurs when attempting to run a query, we'll format the error
668| // message to include the bindings with SQL, which will make this exception a
669| // lot more helpful to the developer instead of just the database's errors.
670| catch (Exception $e) {
> 671| throw new QueryException(
672| $query, $this->prepareBindings($bindings), $e
673| );
674| }
675|
1 D:\Applications\laragon\www\ToDoApp\vendor\laravel\framework\src\Illuminate\Database\Connection.php:464
PDOException::("SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint")
2 D:\Applications\laragon\www\ToDoApp\vendor\laravel\framework\src\Illuminate\Database\Connection.php:464
PDOStatement::execute()
应该注意的是,我可以直接在 PHPMyAdmin GUI 中实现我需要的东西,或者使用基本的 PHP PDO,但我不明白 Eloquent 和需要了解我做错了什么。
我感觉这与两次 table 迁移之间的属性定义不匹配有关,但我尝试的一些事情导致了交替错误。
用以下代码替换您的 items
迁移:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateItemsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('items', function (Blueprint $table) {
$table->id();
$table->integer('user_id')->unsigned();
$table->string('itemName');
$table->string('itemDescription');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('items');
}
}
列的类型和符号必须相同(有符号或无符号)
$table->integer('user_id')->unsigned();
应该是 $table->bigInteger('user_id')->unsigned();
只需为外键 (docs) 制作一个新的迁移文件。像
php artisan make:migration add_columns_to_items_table
为什么对同一个 table 使用不同的文件?因为我们在设置 foreignKey 之前先设置了 table 对吗? :)
然后在 up() 函数的迁移文件中:
Schema::table('items', function (Blueprint $table) {
$table->foreignId('user_id')->constrained();
});
是的,它更短更好用于开发目的
当您在 one-to-many
关系的 one
部分之前为 many
创建迁移时,会发生这种情况。在您的情况下,我猜您在 users
之前为 items
创建了迁移。只需根据您的关系重命名您的迁移文件。另请注意,您的关系列必须属于同一类型。在您的情况下,您引用的是 4 字节的 integer
到 8 字节的 bigInteger
。 (id
列是一个 unsigned
8 字节整数)。