2013-07-04 19 views
60

我有一個多對多的關係建立和工作,將項目添加到我用的車:防止Laravel添加多個記錄透視表

$cart->items()->attach($item); 

它增加了一個項目的透視表(因爲它應該),但是如果用戶再次點擊鏈接添加他們已經添加的項目,它會在數據透視表中創建一個重複的條目。

是否有內置的方式將數據只添加到數據透視表中,如果尚不存在?

如果不是,我該如何檢查數據透視表以查找匹配記錄是否已經存在?

回答

54

您可以通過編寫一個非常簡單的條件這樣一個檢查現有記錄的存在:

if (! $cart->items->contains($newItem->id)) { 
    $cart->items()->save($newItem); 
} 

或/和你可以在數據庫中添加單一性條件下,它會嘗試過程中拋出一個異常節省一雙。

你還應該看看下面Barryvdh的更直接的答案。

+1

的方法'附上()'是混合,它可以是模型的一個int或實例的$ id參數;) - 見https://github.com/laravel /framework/blob/master/src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php?source=cc#L589 –

+0

謝謝@RobGordijn。我今天學到了一些東西!回答編輯。 –

+0

'包含'聲明的目的是什麼?它無法找到任何重複的內容,所以當我使用這個時,我仍然有重複錯誤。 –

2

@alexandre Butynsky方法工作得很好,但使用兩個SQL查詢。

一個用來檢查購物車是否包含該物品,另一個用於保存。

要使用只有一個查詢使用:

try { 
    $cart->items()->save($newItem); 
} 
catch(\Exception $e) {} 
+0

這就是我在我的項目中做的。但問題是你不知道這個異常是否是由重複條目或其他引起的。 –

+1

爲什麼會拋出異常?這將是如果有一些獨特的鑰匙 –

169

您還可以使用$model->sync(array $ids, $detaching = true)方法和禁止拆卸(第二PARAM)。

$cart->items()->sync([$item->id], false); 

更新: 由於Laravel 5.3或5.2.44,你也可以撥打syncWithoutDetaching:

$cart->items()->syncWithoutDetaching([$item->id]); 

這不完全一樣,但更具可讀性:)

+9

有史以來最聰明的答覆。 –

+2

防止分離未列出ID的第二個布爾參數不在L5主文檔中。這是很好的知道 - 似乎是在一個聲明中「附加,如果尚未附上」的唯一途徑。 – Jason

+3

這應該被接受爲答案,它是一個比接受的答案更好的方法 – Daniel

0

一樣好一切這個答案是因爲我試過了所有的東西,有一件事仍然沒有解決或者沒有照顧到:更新一個先前選中的值的問題(取消選中複選框[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); 
}