У меня установлено и работает множество отношений, чтобы добавить товар в корзину, которую я использую:
$cart->items()->attach($item);
Это добавляет элемент в сводную таблицу (как и должно), но если пользователь снова щелкает ссылку, чтобы добавить уже добавленный элемент, в сводной таблице создается повторяющаяся запись.
Есть ли встроенный способ добавления записи в сводную таблицу, только если она еще не существует?
Если нет, как я могу проверить сводную таблицу, чтобы определить, существует ли уже соответствующая запись?
attach()
смешанный, это может быть int или экземпляр модели;) - см. Github.com/laravel/framework/blob/master/src/Illuminate/…contains
проверяет, присутствует ли ключ в одном объекте в коллекции. У вас должна быть ошибка в вашем коде.$cart->items()->where('foreign_key', $foreignKey)->count()
Что, ну, на самом деле, тоже выполняет дополнительный запрос '^^ Но мне не нужно получать и гидратировать всю коллекцию, если она мне действительно не нужна.exists()
функцию вместоcount()
для лучшей оптимизации.Вы также можете использовать
$model->sync(array $ids, $detaching = true)
метод и отключить отсоединение (второй параметр).$cart->items()->sync([$item->id], false);
Обновление: начиная с Laravel 5.3 или 5.2.44, вы также можете вызвать syncWithoutDetaching:
Что делает то же самое, но более читабельно :)
источник
$cart->items()->sync([1, 2, 3])
будут строить много-ко-многим к идентификаторам в данном массиве1
,2
и3
, и удаление (или «открепление») все другие идентификаторы не в массиве. Таким образом, в таблице будет существовать только идентификатор, указанный в массиве. Brilliant @Barryvdh использует недокументированный второй параметр для отключения этого отсоединения, поэтому никакие отношения, не входящие в данный массив, не удаляются, а только уникальные идентификаторы будут прикреплены. Ознакомьтесь с документом «Синхронизация для удобства». (Laravel 5.2)syncWithoutDetaching()
, который вызывает sync () со вторым параметром false.syncWithoutDetaching()
работал!Метод @alexandre Butynsky работает очень хорошо, но использует два sql-запроса.
Один для проверки наличия товара в корзине и один для сохранения.
Чтобы использовать только один запрос, используйте это:
try { $cart->items()->save($newItem); } catch(\Exception $e) {}
источник
Как бы хороши ни были все эти ответы, потому что я перепробовал их все, одна вещь все еще осталась без ответа или не решена: проблема обновления ранее отмеченного значения (снята отметка с флажком [es]). У меня есть что-то похожее на приведенный выше вопрос, ожидаю, что я хочу проверять и снимать флажки функций продуктов в моей таблице функций продукта (сводная таблица). Я новичок и понял, что ничего из вышеперечисленного не помогло. Оба они хороши при добавлении новых функций, но не тогда, когда я хочу удалить существующие функции (т.е. снять флажок).
Я буду признателен за любое разъяснение по этому поводу.
$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); }
или
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); }
Извините, ребята, не уверен, что мне следует удалить вопрос, потому что, когда я сам определил ответ, это звучит немного глупо, ну, ответ на приведенный выше так же прост, как работа @Barryvdh sync () следующим образом; прочитав все больше и больше о:
$features = $request->get('features'); if (isset($features) && Count($features)>0){ $product->features()->sync($features); }
источник
Уже есть несколько отличных ответов. Хотя я хотел выбросить и эту.
Ответы @AlexandreButynski и @Barryvdh более читабельны, чем мое предложение, этот ответ добавляет некоторую эффективность.
Он извлекает только записи для текущей комбинации (фактически только идентификатор), а затем присоединяет ее, если она не существует. Метод синхронизации (даже без отсоединения) извлекает все подключенные в данный момент идентификаторы. Для небольших наборов с небольшими итерациями это вряд ли будет иметь значение ... вы поняли мою точку зрения.
В любом случае, это определенно не так читабельно, но это помогает.
if (is_null($book->authors()->find($author->getKey(), [$author->getQualifiedKeyName()]))) $book->authors()->attach($author);
источник