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.

È stato utile?

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);

        }
    }
});
.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top