2014-10-05 28 views
1

我试图让外键约束在Laravel中工作。但我似乎无法挽救我的模型了。Laravel与外键约束的模型关系

我的数据库结构的设置如下(I已移除不必要的代码):

Schema::create($this->tableName, function(Blueprint $table) 
{ 
    $table->increments('id'); 

    $table->string('username')->unique(); 
    $table->string('password', 64); 

    $table->integer('address_id')->unsigned(); 
}); 

Schema::create($this->tableName, function(Blueprint $table) 
{ 
    $table->increments('id'); 

    $table->integer('user_id')->unsigned(); 

    $table->string('name'); 
    $table->string('surname'); 

    $table->string('street'); 
    $table->string('number'); 
    $table->string('town'); 
    $table->string('country'); 
}); 

所以Address是在一个单独的表和Address属于UserUser有一个Address

接下来,我已经创建了相应的机型:

Class User extends Model 
{ 
    public function address() 
    { 
     return $this->hasOne('Address'); 
    } 
} 

Class Address extends Model 
{ 
    public function user() 
    { 
     return $this->belongsTo('User'); 
    } 
} 

现在,当我尝试创建与Address一个User并保存它,我得到的约束错误。我试过两种方法(先保存User并先保存Address),但都出错。

我的第一个想法是这样的:

// Create a new user 
$user = new User($data); 
$address = new Address($addressData); 

$address->user()->associate($user); 
$user->push(); // Error here 

但这给出了错误:

SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`eet`.`users`, CONSTRAINT `users_address_id_foreign` FOREIGN KEY (`address_id`) REFERENCES `addresses` (`id`)) (SQL: insert into `users` (`username`, `email`, `password`, `type`, `phone`, `cellphone`, `newsletter_week`, `ip`, `updated_at`, `created_at`) values (adsadsad, [email protected], passWO23dw00, customer, 123123213, 1234567890, 1, ::1, 2014-10-05 19:56:03, 2014-10-05 19:56:03)) 

所以,我想保存Address第一,然后User,如:

$user = new User($data); 

$address = new Address($addressData); 
$address->save(); // Error here 

$address->user()->associate($user); 
$user->push(); 

但是,然后生成以下错误:

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'user_id' cannot be null (SQL: insert into `addresses` (`name`, `surname`, `street`, `number`, `town`, `country`, `user_id`) values (Foo, Bar, FooStreet, 200, Townsville, nl,)) 

那么这样做的好方法是什么?我可以将User设置为空的address_id,但是这是一种很好的做法吗?我想要一个User始终有一个Address

回答

0

起初救母model在这种情况下它是User这样:

$user = new User($data); 
$user->save(); 

然后尝试:

// $addressData ... 
$addressData['user_id'] = $user->id; 
$address = new Address($addressData); 
$address->save(); 

或许:

$user = new User($data); 
$user->address = new Address($addressData); 
$user->push(); 
+0

我会说'用户'是这里的“定义实体”。而'用户'有一个'地址'。我认为你的意思是:“从'Address'中删除'user_id',你很好走。”但是,我可以制作“孤儿”地址。 – Matthijn 2014-10-05 18:19:09

+0

你的“地址”表是否有'user_id'? – 2014-10-05 18:20:08

4

我将开始与数据库首先设计。

对于users表我会用:

$table->increments('id'); 

$table->string('username')->unique(); 
$table->string('password', 64); 

ADDRESS_ID是没有必要在这里。

对于addresses表我会用:

$table->increments('id'); 

$table->integer('user_id')->unsigned(); 

$table->string('name'); 
$table->string('surname'); 

$table->string('street'); 
$table->string('number'); 
$table->string('town'); 
$table->string('country'); 
$table->foreign('user_id') 
     ->references('id') 
     ->on('users') 
     ->onDelete('CASCADE'); 

你应该在地址表中使用外键,并添加onDelete('CASCADE`) - 现在,如果你删除用户,地址将被自动删除。你不会有任何孤立的地址。

现在插入数据:

$user = new User($data); 
$user->save(); 
$address = new Address($addressData); 
$user->address()->save($address); 

你并不需要把$addressData任何user_id - 它会自动填写。

+0

是的,那是一种可能性。但我想区分家庭地址和(物理)邮件地址。所以我在users表中有一个'address_id'和'delivery_address_id'。如果我从用户中删除address_id,我将无法区分。 – Matthijn 2014-10-05 20:26:52

+0

@Matthijn所以用户表中的address_id与Address模型没什么共同之处? – 2014-10-05 20:32:22