Laravel को पिवट टेबल में कई रिकॉर्ड जोड़ना रोकना


98

मेरे द्वारा उपयोग की जाने वाली गाड़ी में एक आइटम जोड़ने के लिए मेरे पास बहुत से संबंध स्थापित करने और काम करने के लिए एक है:

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

जो पिवट टेबल में एक आइटम जोड़ता है (जैसा कि यह होना चाहिए), लेकिन अगर उपयोगकर्ता लिंक पर फिर से क्लिक करता है तो वे एक आइटम जोड़ने के लिए जो उन्होंने पहले ही जोड़ा है वह पिवट टेबल में एक डुप्लिकेट प्रविष्टि बनाता है।

क्या एक पिवट टेबल में रिकॉर्ड जोड़ने के लिए केवल एक अंतर्निहित तरीका है यदि कोई पहले से मौजूद नहीं है?

यदि नहीं, तो मैं मिलान तालिका पहले से मौजूद है या नहीं यह जानने के लिए मैं पिवट टेबल की जांच कैसे कर सकता हूं?

जवाबों:


76

आप इस तरह की एक बहुत ही सरल स्थिति लिखकर एक मौजूदा रिकॉर्ड की उपस्थिति की जांच कर सकते हैं:

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

या / और आप अपने डेटाबेस में एकता की स्थिति जोड़ सकते हैं, यह एक बचत को बचाने के प्रयास के दौरान एक अपवाद को फेंक देगा।

आपको बस नीचे दिए गए बृजबोध से अधिक सीधे उत्तर पर एक नज़र डालनी चाहिए।


1
विधि के लिए $ आईडी पैरामीटर attach()मिलाया जाता है, यह एक इंट या मॉडल का उदाहरण हो सकता है;) - देखें github.com/laravel/framework/blob/master/src/Illuminate/…
Rob Gordijn

साभार @RobGordijn मैंने आज कुछ सीखा है! उत्तर संपादित किया गया।
एलेक्जेंडर ब्यूटिंस्की

1
@bagusflyer containsस्टेटमेंट की जाँच करें कि क्या कलेक्शन में एक ऑब्जेक्ट मौजूद है। आपको अपने कोड में गलती करनी चाहिए।
एलेक्जेंडर ब्यूटिंस्की

4
मुझे यह समाधान पसंद नहीं है क्योंकि यह एक अतिरिक्त क्वेरी ($ कार्ट-> आइटम) पर काम कर रहा है, मैं कुछ ऐसा कर रहा हूं: $cart->items()->where('foreign_key', $foreignKey)->count() जो, ठीक है, वास्तव में एक अतिरिक्त क्वेरी भी करता है '^ ^ लेकिन मुझे लाने की आवश्यकता नहीं है और जब तक मुझे वास्तव में इसकी आवश्यकता न हो, तब तक पूरे संग्रह को हाइड्रेट करें।
मौन

1
यह सही है, आपका समाधान थोड़ा और अधिक अनुकूलित है। तुम भी सबसे अच्छा अनुकूलन exists()के count()लिए के बजाय समारोह का उपयोग कर सकते हैं ।
एलेक्जेंडर ब्यूटिंस्की

265

आप $model->sync(array $ids, $detaching = true)विधि का उपयोग भी कर सकते हैं और कोचिंग को निष्क्रिय कर सकते हैं (दूसरा परम)।

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

अपडेट: लारवेल 5.3 या 5.2.44 के बाद से, आप सिंक को कॉल भी कर सकते हैं। कोचिंग:

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

जो बिल्कुल वैसा ही करता है, लेकिन अधिक पठनीय :)


2
असूचीबद्ध आईडी को रोकने के लिए दूसरा बूलियन पैरामीटर मुख्य L5 प्रलेखन में नहीं है। यह जानना बहुत अच्छा है - एक ही कथन में "यदि पहले से संलग्न नहीं है तो" संलग्न करने का एकमात्र तरीका प्रतीत होता है।
जेसन

11
इसे उत्तर के रूप में स्वीकार किया जाना चाहिए, यह स्वीकृत उत्तर की तुलना में इसे करने का एक बेहतर तरीका है
डैनियल

4
मेरे जैसे नवागंतुकों के लिए: $cart->items()->sync([1, 2, 3])दी सरणी में पहचान-पत्र बनाने के लिए कई-से-अनेक संबंधों का निर्माण करेगी, 1, 2, और 3, और हटाने (या "अलग") सभी अन्य आईडी नहीं सरणी में है। इस तरह, सारणी में दी गई आईडी की केवल आईडी मौजूद होगी। शानदार @Barryvdh उस डिटैचिंग को निष्क्रिय करने के लिए एक अनिर्दिष्ट दूसरे पैरामीटर का उपयोग करता है, इसलिए दिए गए सरणी में कोई भी संबंध हटाए नहीं जाते हैं, लेकिन केवल अनन्य आईडी को संलग्न किया जाएगा। "संयम के लिए समन्वय" डॉक्टर की जाँच करें। (
लारवेल

3
FYI करें, मैंने डॉक्स को अपडेट किया, तो 5.2 और ऊपर: laravel.com/docs/5.2/… और टेलर ने तुरंत ऐड जोड़ा syncWithoutDetaching(), जो सिंक () को दूसरे परम के रूप में गलत कहता है।
१०:२१ पर बरगदडीह

लारवेल ५.५ लार्वेल.com/docs/ 5.5/ syncWithoutDetaching() ने काम किया!
जोश लामार

2

@alexandre Butynsky विधि बहुत अच्छी तरह से काम करती है लेकिन दो sql प्रश्नों का उपयोग करती है।

एक यह जांचने के लिए कि कार्ट में आइटम है और एक को बचाने के लिए।

इसका उपयोग करने के लिए केवल एक क्वेरी का उपयोग करें:

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

यही मैंने अपने प्रोजेक्ट में किया है। लेकिन समस्या यह है कि क्या आप नहीं जानते कि यह अपवाद डुप्लिकेट प्रविष्टि या किसी अन्य चीज़ के कारण है।
Bagusflyer

2
यह कोई अपवाद क्यों फेंकेगा? यह होगा अगर वहाँ कुछ अद्वितीय कुंजी है
Seiji Manoan

1

जैसा कि यह सभी उत्तर अच्छे हैं क्योंकि मैंने उन सभी को आज़माया था, एक बात अभी भी पूरी नहीं है या ध्यान नहीं दिया गया है: पहले से चेक किए गए मान को अपडेट करने की समस्या (चेक बॉक्स को अनचेक किया गया] [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 सिंक () निम्नानुसार है; अधिक से अधिक पढ़ने के बारे में:

$features = $request->get('features');
if (isset($features) && Count($features)>0){
    $product->features()->sync($features);
}

0

कुछ शानदार उत्तर पहले से ही पोस्ट किए गए हैं। मैं इस एक को यहाँ भी फेंकना चाहता था।

@AlexandreButynski और @Barryvdh के उत्तर मेरे सुझाव से अधिक पठनीय हैं, जो इस उत्तर को जोड़ता है वह कुछ दक्षता है।

यह केवल वर्तमान संयोजन (वास्तव में केवल आईडी) के लिए प्रविष्टियों को पुनर्प्राप्त करता है और यह मौजूद नहीं होने पर इसे संलग्न करता है। सिंक विधि (यहां तक ​​कि बिना कोचिंग) सभी वर्तमान में संलग्न आईडी को पुनः प्राप्त करता है। छोटे पुनरावृत्तियों के साथ छोटे सेटों के लिए यह शायद ही अंतर होगा, ... आपको मेरी बात मिल जाएगी।

वैसे भी, यह निश्चित रूप से पठनीय नहीं है, लेकिन यह चाल करता है।

if (is_null($book->authors()->find($author->getKey(), [$author->getQualifiedKeyName()])))
    $book->authors()->attach($author);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.