Laravelピボットテーブルの関連付けを1回作成してから更新します
質問
次の表があります:
user:
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
....
.
edit 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
を持つ行があることを意味し、それ以外の場合は正常に更新されています。そのため、新しい行を作成するために添付することができます
$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);
}
}
});
.