回答:
次のような非常に単純な条件を記述することにより、既存のレコードの存在を確認できます。
if (! $cart->items->contains($newItem->id)) {
$cart->items()->save($newItem);
}
または、データベースに単一性条件を追加できます。ダブレットを保存しようとすると例外がスローされます。
また、すぐ下のBarryvdhからのより簡単な答えも見てください。
contains
ステートメントは、キーがコレクション内の1つのオブジェクトに存在するかどうかを確認します。コードに間違いがあるはずです。
$cart->items()->where('foreign_key', $foreignKey)->count()
ことをしています。本当に必要でない限り、コレクション全体に水分を補給します。
exists()
代わりに関数を使用することもできcount()
ます。
$model->sync(array $ids, $detaching = true)
メソッドを使用して、デタッチを無効にすることもできます(2番目のパラメーター)。
$cart->items()->sync([$item->id], false);
更新:Laravel 5.3または5.2.44以降、syncWithoutDetachingを呼び出すこともできます。
$cart->items()->syncWithoutDetaching([$item->id]);
まったく同じですが、より読みやすくなっています:)
$cart->items()->sync([1, 2, 3])
指定した配列内のIDのへの多対多の関係を構築します、1
、2
、及び3
、削除(または「デタッチ」)他のすべてのIDは配列ではありません。この方法では、配列で指定されたIDのみがテーブルに存在します。Brilliant @Barryvdhは、文書化されていない2番目のパラメーターを使用してその切り離しを無効にするため、指定された配列にない関係は削除されず、一意のIDのみがアタッチされます。「同期のための同期」ドキュメントを確認してください。(Laravel 5.2)
syncWithoutDetaching()
、2番目のパラメーターとしてfalseを指定してsync()を呼び出します。
syncWithoutDetaching()
機能しました!
@alexandre Butynskyメソッドは非常にうまく機能しますが、2つのSQLクエリを使用します。
カートに商品が含まれているかどうかを確認するものと、保存するものです。
1つのクエリのみを使用するには、これを使用します。
try {
$cart->items()->save($newItem);
}
catch(\Exception $e) {}
これらすべての回答と同じくらい良いのは、私がそれらすべてを試したためです。1つは、未回答のままであるか、処理されないままです。以前にチェックされた値を更新する問題(チェックされたボックスのチェックを外した問題)。上記の質問に似たものがありますが、製品機能テーブル(ピボットテーブル)で製品の機能をチェックおよびチェック解除したいと思っています。私は初心者であり、上記のどれもそれをしなかったことに気づきました。新しい機能を追加する場合はどちらも優れていますが、既存の機能を削除する場合はチェックを外します(つまり、チェックを外します)。
私はこれについてのあらゆる啓蒙に感謝します。
$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);
}
そのまま使えます
$cart->items()->sync($items)
Laravel 5.7以降:
関連の同期syncメソッドを使用して、多対多の関連を構築することもできます。syncメソッドは、中間テーブルに配置するIDの配列を受け入れます。指定された配列にないIDは、中間テーブルから削除されます。したがって、この操作が完了すると、指定された配列のIDのみが中間テーブルに存在します。
すでにいくつかの素晴らしい回答が投稿されています。これもここに捨てたかった。
@AlexandreButynskiと@Barryvdhからの回答は私の提案よりも読みやすく、この回答が追加するのはある程度の効率です。
現在の組み合わせ(実際にはIDのみ)のエントリのみを取得し、存在しない場合は添付します。syncメソッドは(デタッチなしでも)、現在アタッチされているすべてのIDを取得します。イテレーションが少ない小さなセットの場合、これはほとんど違いがありません。
とにかく、それは間違いなく読みやすくはありませんが、トリックを行います。
if (is_null($book->authors()->find($author->getKey(), [$author->getQualifiedKeyName()])))
$book->authors()->attach($author);
attach()
混合され、それはモデルのintまたはインスタンスとすることができる。) -参照github.com/laravel/framework/blob/master/src/Illuminate/...