laravel设置了一个外键

时间:2014-08-10 20:14:37

标签: php mysql laravel-4

我是laravel的新手。我正在做一个项目,用户首先注册,他的信息将存储在用户表中。然后他或她登录网站,用户将提供另一个注册表格作为献血者。这个信息将存储另一个表,即 blooddonners table.so我想在 blooddonner 表中创建一个外键。foreingn键将是 id 来自用户表。这就是为什么我为 blooddonner 表创建了一个迁移,

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateBlooddonnerTable extends Migration {

/**
 * Run the migrations.
 *
 * @return void
 */
public function up()
{
    Schema::create('blooddonners', function(Blueprint $table)
    {
        $table->increments('id');
        $table->unsignedInteger('donner_id');
        $table->foreign('donner_id')->references('id')->on('users')->onDelete('cascade')->onUpdate('cascade');
        $table->string('donner_name');
        $table->string('email')->unique();
        $table->string('blood_group');
        $table->string('phone_number')->unique();
        $table->string('location');
        $table->date('date_of_birth');
        $table->date('last_date_of_donation');
        $table->timestamps();
    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    Schema::drop('blooddonners');
}

}

但在提交表格后,我面临以下错误,

Illuminate \ Database \ QueryException
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row:    a foreign key constraint fails (`needa`.`blooddonners`, CONSTRAINT    `blooddonners_donner_id_foreign` FOREIGN KEY (`donner_id`) REFERENCES `users` (`id`) ON    DELETE CASCADE ON UPDATE CASCADE) (SQL: insert into `blooddonners` (`date_of_birth`,    `blood_group`, `location`, `email`, `phone_number`, `last_date_of_donation`, `updated_at`,    `created_at`) values (2014-08-06, A-, SHERPUR, raihn_cse@yahoo.com, 01796580404, 2014-08-  20, 2014-08-10 19:42:38, 2014-08-10 19:42:38))
虽然我在Laravel中很新,所以我有疑问,我在迁移文件中设置外来的方式,是设置外键的方法吗?,导致错误与该外键有关。 / p>

1 个答案:

答案 0 :(得分:1)

您设置外键的方式没有任何问题。证明这一点就是MySQL实际上阻止你插入违反你告诉它强制执行的外键的条目。问题是您尝试添加blood donor条目而未指定与其相关的user。您有两种选择:

  1. 在您用于添加新献血者的查询中,指定相关用户的ID;
  2. 即使donor_id是外键,如果这是你想要的,它也可以是可空的,尽管你需要告诉Laravel / MySQL。
  3. 以下是定义可空列的方法:

    $table->unsignedInteger('donor_id')->nullable();
    

    我冒昧地纠正你的拼写: blood donner&gt;献血者。正确的拼写也有助于编码可读性;)


    修改

    如果您想要了解如何改进数据库设计以便充分利用外键,请按以下步骤操作:

    第一件事:如果不是每个用户都是献血者,我只会有一个辅助blood_donors表。如果100%的用户都是献血者,请不要过于复杂:只使用一个表并添加更多列。否则,请继续阅读。

    我的users表可能包含与一般个人信息相关的所有列:

    • 名称
    • 电子邮件
    • 电话号码(用户唯一
    • 位置
    • 出生日期

    之后,我可以通过users“链接”blood_donors表和foreign keys表,这样我就不必重复了。我需要知道的是哪个用户对应哪个献血者,而我需要完成的只是一个id。这样,当我对数据库进行查询时,无论它是最初位于blood_donors还是users表,我都可以轻松地join两个表一起并一次拥有所有数据,在两个不同的地方重复它。

    所以,回到你的迁移,现在就足够了:

    Schema::create('blooddonners', function(Blueprint $table)
    {
        $table->increments('id');
        $table->unsignedInteger('user_id');
        $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade')->onUpdate('cascade');
        $table->string('blood_group');
        $table->date('last_date_of_donation');
        $table->timestamps();
    });
    

    即。你不需要blood_donors表中的“捐赠者姓名”,因为你已经将它记录在你的用户桌面上,毕竟他们是同一个人。您应该只有在献血背景下才有相关的列。

    然后,您可以使用这样的查询访问所有这些数据(假设您已经设置了模型):

    User::join('blood_donors', 'users.id', '=', 'blood_donors.user_id')->get();
    

    你有一个同时包含两个表列的对象。请注意,具有完全相同名称的列将在最终对象中相互覆盖,因此如果要在该对象中可靠地访问ids,则最好在select部分指定别名的查询。如果必须,您甚至可以更改列名称。在Laravel你可以这样做:

    User::select('users.*', 'users.name as donor_name', 'blood_donors.id as donor_id')
        ->join('blood_donors', 'users.id', '=', 'blood_donors.user_id')
        ->get();
    

    查看Eloquent documentation on relationships,了解如何进一步完善数据库设计,并保持清晰,可读的代码。