Mam skonfigurowaną i działającą relację wiele do wielu, aby dodać przedmiot do koszyka, którego używam:
$cart->items()->attach($item);
Powoduje to dodanie elementu do tabeli przestawnej (tak jak powinno), ale jeśli użytkownik ponownie kliknie łącze, aby dodać element, który już dodał, tworzy zduplikowany wpis w tabeli przestawnej.
Czy istnieje wbudowany sposób dodawania rekordu do tabeli przestawnej tylko wtedy, gdy taki rekord jeszcze nie istnieje?
Jeśli nie, jak mogę sprawdzić tabelę przestawną, aby dowiedzieć się, czy pasujący rekord już istnieje?
attach()
jest mieszany, może to być int lub instancja modelu;) - patrz github.com/laravel/framework/blob/master/src/Illuminate/ ...contains
sprawdza, czy klucz jest obecny w jednym obiekcie w kolekcji. Powinieneś mieć błąd w swoim kodzie.$cart->items()->where('foreign_key', $foreignKey)->count()
Które, cóż, faktycznie wykonuje również dodatkowe zapytanie '^^ Ale nie muszę pobierać i nawadniaj całą kolekcję, chyba że naprawdę tego potrzebuję.exists()
funkcji zamiastcount()
dla najlepszej optymalizacji.Możesz także skorzystać z tej
$model->sync(array $ids, $detaching = true)
metody i wyłączyć odłączanie (drugi parametr).$cart->items()->sync([$item->id], false);
Aktualizacja: Od Laravel 5.3 lub 5.2.44 możesz także wywołać syncWithoutDetaching:
Co robi dokładnie to samo, ale bardziej czytelne :)
źródło
$cart->items()->sync([1, 2, 3])
wybuduje wiele do wielu relacji do identyfikatora użytkownika w danej tablicy1
,2
i3
, i usuń (lub „odłączyć”) wszystkie pozostałe id nie jest w tablicy. W ten sposób w tabeli będą istnieć tylko identyfikatory podane w tablicy. Brilliant @Barryvdh używa nieudokumentowanego drugiego parametru, aby wyłączyć to odłączanie, więc żadne relacje spoza danej tablicy nie są usuwane, ale dołączane są tylko unikalne identyfikatory. Zapoznaj się z dokumentem „Synchronizacja dla wygody”. (Laravel 5.2)syncWithoutDetaching()
, który wywołuje sync () z fałszem jako drugim parametrem.syncWithoutDetaching()
działał!Metoda @alexandre Butynsky działa bardzo dobrze, ale używa dwóch zapytań sql.
Jeden do sprawdzenia, czy koszyk zawiera przedmiot, a drugi do zapisania.
Aby użyć tylko jednego zapytania, użyj tego:
try { $cart->items()->save($newItem); } catch(\Exception $e) {}
źródło
Wszystkie te odpowiedzi są dobre, ponieważ wypróbowałem je wszystkie, ale jedna rzecz pozostaje bez odpowiedzi lub nie została załatwiona: kwestia aktualizacji wcześniej zaznaczonej wartości (odznaczono zaznaczone pole [es]). Mam coś podobnego do powyższego pytania, spodziewam się, że chcę zaznaczyć i odznaczyć cechy produktów w mojej tabeli cech produktów (tabeli przestawnej). Jestem nowicjuszem i zdałem sobie sprawę, że żaden z powyższych nie zrobił tego. Oba są dobre przy dodawaniu nowych funkcji, ale nie wtedy, gdy chcę usunąć istniejące funkcje (tj. Odznacz je)
Docenię każde oświecenie w tej sprawie.
$features = $request->get('features'); if (isset($features) && Count($features)>0){ foreach ($features as $feature_id){ $feature = Feature::whereId($feature_id)->first(); $product->updateFeatures($feature); } } //product.php (extract) public function updateFeatures($feature) { return $this->features()->sync($feature, false); }
lub
public function updateFeatures($feature) { if (! $this->features->contains($features)) return $this->features()->attach($feature); } //where my attach() is: public function addFeatures($feature) { return $this->features()->attach($feature); }
Przepraszam, nie jestem pewien, czy powinienem usunąć to pytanie, ponieważ po samodzielnym znalezieniu odpowiedzi brzmi to trochę głupio, cóż, odpowiedź na powyższe jest tak prosta, jak praca @Barryvdh sync () w następujący sposób; czytając coraz więcej o:
$features = $request->get('features'); if (isset($features) && Count($features)>0){ $product->features()->sync($features); }
źródło
Opublikowano już kilka świetnych odpowiedzi. Jednak ten też chciałem wyrzucić.
Odpowiedzi @AlexandreButynski i @Barryvdh są bardziej czytelne niż moja sugestia, co dodaje ta odpowiedź, to pewna efektywność.
Pobiera tylko wpisy dla bieżącej kombinacji (właściwie tylko identyfikator) i dołącza ją, jeśli nie istnieje. Metoda synchronizacji (nawet bez odłączania) pobiera wszystkie aktualnie dołączone identyfikatory. W przypadku mniejszych zestawów z małymi iteracjami nie będzie to żadna różnica, ... rozumiesz.
W każdym razie na pewno nie jest tak czytelny, ale załatwia sprawę.
if (is_null($book->authors()->find($author->getKey(), [$author->getQualifiedKeyName()]))) $book->authors()->attach($author);
źródło