Laravel 数据透视表创建关联一次,然后更新
题
我有以下表格:
用户:
userID
...
课:
lessonID
...
Users_Lessons_Status(充当数据透视表并保存其他信息):
userID references User.userID
lessonID references Lessons.lessonID
latestSectionID
percentComplete
我想要做的是,对于每个用户,对于每节课,数据透视表中应该有一行告诉用户在该课中完成了多少内容以及他们的最新部分 ID 是什么。也就是说,应该有一个唯一的对 userID
和 lessonID
(主键?)。
我已经像这样设置了我的模型:
<?php
class User extends Eloquent implements UserInterface, RemindableInterface {
...
public function lessonStatuses()
{
return $this->belongsToMany('Lesson', 'users_lessons_status', 'lessonID', 'userID')->withPivot('latestSectionID', 'percentComplete');
}
}
<?
class Lesson extends Eloquent {
protected $table = 'lessons';
protected $primaryKey = 'lessonID';
public function userStatuses()
{
return $this->belongsToMany('User', 'users_lessons_status', 'userID', 'lessonID');
}
}
?>
我当前的路线如下:
Route::post('dbm/users/setLatestSectionID', function() {
if(Auth::check()) {
$user = User::find(Input::get('userID'));
$lesson = Lesson::find(Input::get('lessonID'));
$us = $user->lessonStatuses();
$us->attach($lesson->lessonID,
["latestSectionID" => Input::get('latestSectionID'), "percentComplete" => Input::get('percentComplete')] );
}
});
这是有效的,但是,每次我更新相同的行时,它都会创建一个新行 userID
和 lessonID
, ,所以这对不再是唯一的。我应该使用哪些方法来达到此目的?我都尝试过 save()
, attach()
和 push()
在文档中,但我不确定这里使用哪一个。
编辑:为了澄清,结果表应该如下所示:
id|userID|lessonID|latestSectionID|percentComplete
1 1 1 X Y
2 1 2
3 1 3
4 2 1
5 3 1
6 3 2
....
编辑2:修复了 User->belongsToMany()
方法并添加了 withPivot
称呼。
解决方案
这看起来像是一个错误,但你可以这样做:
...->sync([$id], false); // detaching set to false, so it will only insert new rows, skip existing and won't detach anything
编辑:正如评论中所述 - 它对您不起作用,因为您想设置枢轴数据。所以基本上目前没有方法可以做到这一点,但应该这样做:
// belongsToMany.php
public function attachOrUpdate($id, array $attributes = array(), $touch = true)
{
if ($id instanceof Model) $id = $id->getKey();
if ( ! $this->allRelatedIds()->contains($id)) // getRelatedIds() in prior to v5.4
{
return $this->attach($id, $attributes, $touch);
}
else if ( ! empty($attributes))
{
return $this->updateExistingPivot($id, $attributes, $touch);
}
}
我将对其进行测试,如果通过,则向 4.1 发送拉取请求
其他提示
我最近遇到了这个问题并通过以下方式修复了它:
使用 updateExistingPivot
首先检查结果,如果结果是 1
这意味着有相同的行 userID
和 lessonID
并且已经更新成功,否则,如果结果是 0
这意味着没有行与此相关 userID
和 lessonID
, ,因此您可以附加它以创建新行
$update_result = $us->updateExistingPivot($lesson->lessonID,
["latestSectionID" => Input::get('latestSectionID'), "percentComplete" => Input::get('percentComplete')] );
if($update_result == 0) {
$us->attach($lesson->lessonID,
["latestSectionID" => Input::get('latestSectionID'), "percentComplete" => Input::get('percentComplete')] );
}
你应该使用 updateExistingPivot()
.
更新您的代码以使用
$us->updateExistingPivot($lesson->lessonID,
["latestSectionID" => Input::get('latestSectionID'), "percentComplete" => Input::get('percentComplete')], true );
最后一个参数将更新所有相关模型的时间戳。如果没有,可以删除或设置为 false。
如果您只想在记录不存在时附加,您可以这样做......
Route::post('dbm/users/setLatestSectionID', function() {
if(Auth::check()) {
$user = User::find(Input::get('userID'));
$lesson = [
"latestSectionID" => Input::get('latestSectionID'),
"percentComplete" => Input::get('percentComplete')
];
$num_lessons = $user->lessonStatuses()->where('id', Input::get('lessonID'))->count();
if($num_lessons == 0) {
$user->attach($lesson->lessonID, $lesson);
} else {
$user->updateExistingPivot($lesson->lessonID, $lesson);
}
}
});