Laravel 数据透视表创建关联一次,然后更新

pg-*_*ban 0 php mysql laravel eloquent

我有以下表格:

用户:

userID
...
Run Code Online (Sandbox Code Playgroud)

课:

lessonID
...
Run Code Online (Sandbox Code Playgroud)

Users_Lessons_Status(充当数据透视表并保存其他信息):

userID references User.userID
lessonID references Lessons.lessonID
latestSectionID
percentComplete
Run Code Online (Sandbox Code Playgroud)

我想要做的是,对于每个用户,对于每节课,数据透视表中应该有一行告诉用户在该课中完成了多少内容以及他们的最新部分 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');
}


}

?>
Run Code Online (Sandbox Code Playgroud)

我当前的路线如下:

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')] );
    }
});
Run Code Online (Sandbox Code Playgroud)

然而,这是有效的,每次我为相同的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
....
Run Code Online (Sandbox Code Playgroud)

编辑2:修复了User->belongsToMany()方法并添加了withPivot调用。

Jar*_*zyk 5

这看起来像是一个错误,但你可以这样做:

...->sync([$id], false); // detaching set to false, so it will only insert new rows, skip existing and won't detach anything
Run Code Online (Sandbox Code Playgroud)

编辑:正如评论中所说 - 它对你不起作用,因为你想设置枢轴数据。所以基本上目前没有方法可以做到这一点,但应该这样做:

// 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我将对其进行测试,如果通过,则向 4.1 发送拉取请求

  • @SarahKemp 是的,谢谢,已编辑。这就是 Laravel 的诅咒 - 以一种几乎没有任何价值的方式改变公共接口,但却给消费者带来了很多 BC 破坏性问题 (2认同)

小智 5

我最近遇到了这个问题并通过以下方式修复了它:

首先使用updateExistingPivot并检查 result ,如果 result 是,1则表示存在具有相同userID和的行lessonID,并且已成功更新,否则,如果 result 是,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')] );
    }
Run Code Online (Sandbox Code Playgroud)