Php Laravel pivot表创建关联一次,然后更新
我有以下表格: 用户: 教训:Php Laravel pivot表创建关联一次,然后更新,php,mysql,laravel,eloquent,Php,Mysql,Laravel,Eloquent,我有以下表格: 用户: 教训: lessonID ... 用户\u课程\u状态(充当数据透视表并保存其他信息): 我想做的是,对于每个用户,对于每个课程,pivot表中应该有一行,告诉用户在该课程中完成了多少,以及他们最新的部分ID是什么。也就是说,应该有一对唯一的userID和lessonID(主键?) 我的模型设置如下: <?php class User extends Eloquent implements UserInterface, RemindableInterface {
lessonID
...
用户\u课程\u状态(充当数据透视表并保存其他信息):
我想做的是,对于每个用户,对于每个课程,pivot表中应该有一行,告诉用户在该课程中完成了多少,以及他们最新的部分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');
}
}
?>
但是,这是可行的,每次我为相同的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
....
edit2:修复了
User->belongtomany()
方法,并添加了withPivot
调用 这似乎是一个bug,但您可以这样做:
...->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发送一个pull请求。这看起来像是一个bug,不过您可以这样做:
...->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发送一个pull请求,您应该使用
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);
}
}
});
您应该使用
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);
}
}
});
我最近遇到了这个问题,并通过以下方式解决了它: 首先使用
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
并检查结果,如果结果为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')] );
}
你的意思是这样的:
$us->sync($lesson->lessonID,[“latestSectionID”=>Input::get('latestSectionID'),“percentComplete”=>Input::get('percentComplete'),false)代码>?出于某种原因,它说参数1是一个字符串而不是数组。它应该是$us->sync([$lesson->lessonID,[“latestSectionID”=>…
user2..不,sync不接受属性。pg robban我没有注意到您正在更新(或创建)pivot data。更新了我的答案。@decoz手册上说是的,我记得以前没有这个选项。@SarahKemp true,谢谢,编辑过。这就是Laravel的诅咒-以一种没有任何价值的方式更改公共界面,但却给消费者带来了很多破坏BC的问题。你的意思是:$us->sync($lesson->lessonID,[“latestSectionID”=>Input::get('latestSectionID'),“percentComplete”=>Input::get('percentComplete')),false);
?出于某种原因,它说参数1是字符串而不是数组。它应该是$us->sync([$lesson->lessonID,[“latestSectionID”)=>…
user2..不,同步不接受属性。pg robban我没有注意到您正在更新(或创建)pivot data。更新了我的答案。@decoz手册上说是的,我记得以前没有这个选项。@SarahKemp true,谢谢,经过编辑。这就是Laravel的诅咒——以一种不会带来任何价值的方式更改公共接口,但却会给消费者带来很多破坏BC的问题。这似乎不会在t中创建行可以。对不起,我想这正是你想要的。你想创建一个,除非已经存在一个,在这种情况下你想更新吗?你理解得没错,但也许我需要澄清:当前的attach()
方法在行不存在时创建行。但是,在后续调用中,它会创建额外的行,而不是更新现有行。我想你的意思是,我需要先创建关联,然后调用updateExistingPivot
,对吗?我认为这将是更好的方法,因为一旦你对于dbm/users/setLatestSectionID
路由,我假设已经为课程创建了一个部分。我更新了答案,但在决定attach
或updateExistingPivot
之前,它会首先检查课程。它会让我尝试获取attach行。我认为where
子句有点奇怪。这将检查id
列是否等于lessonID
,但事实并非如此。我已经更新了问题,以澄清表应该是什么样子。这似乎与c无关