La Bellavel Pivot Table crea un'associazione una volta, quindi aggiorna
Domanda
Ho le seguenti tabelle:
Utente:
userID
...
.
Lezione:
lessonID
...
.
Users_lessons_status (che funge da tavolo per pivot e contiene altre informazioni):
userID references User.userID
lessonID references Lessons.lessonID
latestSectionID
percentComplete
.
Quello che voglio fare è, per ogni utente, per ogni lezione, dovrebbe esserci una riga nella tabella pivot che indica quanto l'utente è stato completato in quella lezione e quale fosse il loro ultimo ID della sezione. Cioè, dovrebbe esserci una coppia unica con userID
e lessonID
(chiavi primarie?).
Ho configurato i miei modelli come:
<?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');
}
}
?>
.
La mia rotta corrente sembra questa:
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')] );
}
});
.
Questo funziona, tuttavia, crea una nuova riga ogni volta che lo aggiorno per lo stesso userID
e lessonID
, quindi la coppia non è più unica. Quali metodi dovrei usare per questo scopo? Ho provato sia save()
, attach()
e push()
nella documentazione, ma non sono sicuro di quale utilizzare qui.
Modifica : Per chiarire, la tabella risultante dovrebbe apparire qualcosa del genere:
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
....
.
Modifica 2 : Risolto il metodo User->belongsToMany()
e ha aggiunto la chiamata withPivot
.
Soluzione
Sembra un bug, tuttavia puoi farlo:
...->sync([$id], false); // detaching set to false, so it will only insert new rows, skip existing and won't detach anything
.
Modifica: Come detto nel commento - non funzionerà per te, come vuoi impostare i dati del pivot. Quindi fondamentalmente non c'è metodo per farlo al momento, ma qualcosa del genere dovrebbe fare:
// 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);
}
}
.
Lo testerò e se passa, invia una richiesta di tiro a 4.1
Altri suggerimenti
Ho affrontato questo recentemente e lo aggiustò in questo modo:
Utilizzare innanzitutto il risultato updateExistingPivot
e verificare il risultato, se il risultato è 1
ESSERE C'erano riga con lo stesso userID
e lessonID
ed è stato aggiornato con successo, altrimenti, se il risultato è 0
, significa che non ci sono state righe con questo userID
e lessonID
,Quindi puoi attaccarlo per creare una nuova riga
$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')] );
}
. Dovresti usare updateExistingPivot()
.
Aggiorna il tuo codice da utilizzare
$us->updateExistingPivot($lesson->lessonID,
["latestSectionID" => Input::get('latestSectionID'), "percentComplete" => Input::get('percentComplete')], true );
.
L'ultimo parametro aggiornerà i timestamp per tutti i modelli correlati.In caso contrario, è possibile rimuovere o impostare su FALSE.
Se si desidera allegare solo quando un record non esiste, potresti fare qualcosa come questo ...
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);
}
}
});
.