it-swarm.dev

منع Laravel إضافة سجلات متعددة إلى جدول محوري

لدي العديد من العلاقات التي أقيمت وأعمل ، لإضافة عنصر إلى العربة التي أستخدمها:

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

الذي يضيف عنصرًا إلى الجدول المحوري (كما ينبغي) ، ولكن إذا نقر المستخدم على الرابط مرة أخرى لإضافة عنصر قام بالفعل بإضافته ، فإنه ينشئ إدخالًا مكررًا في الجدول المحوري.

هل هناك طريقة مضمنة لإضافة سجل إلى جدول محوري فقط إذا لم يكن أحد موجودًا بالفعل؟

إذا لم يكن الأمر كذلك ، كيف يمكنني التحقق من الجدول المحوري للعثور على ما إذا كان السجل المطابق موجود بالفعل؟

81
Al_

يمكنك التحقق من وجود سجل موجود عن طريق كتابة شرط بسيط جدًا مثل هذا:

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

أو/ويمكنك إضافة شرط وحيد في قاعدة البيانات الخاصة بك ، فسيؤدي ذلك إلى استثناء أثناء محاولة حفظ doublet.

يجب عليك أيضًا إلقاء نظرة على الإجابة الأكثر وضوحًا من Barryvdh أدناه.

69
Alexandre Butynski

يمكنك أيضًا استخدام الأسلوب $model->sync(array $ids, $detaching = true) وتعطيل الفصل (الحرف الثاني).

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

تحديث: منذ Laravel 5.3 أو 5.2.44 ، يمكنك أيضًا الاتصال بـ syncWithoutDetaching:

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

الذي يفعل بالضبط نفس الشيء ، ولكن أكثر قابلية للقراءة :)

225
Barryvdh

طريقةalexandre Butynsky تعمل بشكل جيد للغاية ولكن استخدم استفساريين اثنين من SQL.

واحد للتحقق مما إذا كانت السلة تحتوي على العنصر وواحد للحفظ.

لاستخدام استعلام واحد فقط ، استخدم هذا:

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

جيدة مثل كل هذه الإجابات لأنني جربتها جميعًا ، لا يزال هناك شيء واحد دون إجابة أو لا يهتم: مشكلة تحديث قيمة تم تحديدها مسبقًا (لم يتم تحديد خانة الاختيار [الخانات المحددة]). لدي شيء مشابه للسؤال أعلاه أتوقع أنني أريد التحقق من ميزات المنتجات وإلغاء تحديدها في جدول ميزات المنتج (الجدول المحوري). أنا مبتدئ وأدركت أن أياً مما سبق لم يفعل ذلك. كلاهما جيد عند إضافة ميزات جديدة ولكن ليس عندما أرغب في إزالة الميزات الموجودة (أي إلغاء تحديدها)

سوف أقدر أي التنوير في هذا.

$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);
}
0
adeguk Loggcity

يمكنك فقط استخدام

$cart->items()->sync($items)

اعتبارًا من Laravel 5.7:

اقتران المزامنة يمكنك أيضًا استخدام طريقة المزامنة لإنشاء اقترانات عديدة. تقبل طريقة المزامنة صفيفًا من المعرفات لوضعه على الجدول المتوسط. ستتم إزالة أي معرفات غير موجودة في الصفيف المحدد من الجدول المتوسط. لذلك ، بعد اكتمال هذه العملية ، سوف توجد فقط معرفات في الصفيف المعطى في الجدول المتوسط:

0
Shreyansh Panchal

هناك بعض الإجابات الرائعة المنشورة بالفعل. أردت أن رمي هذا واحد هنا كذلك.

الإجابات منAlexandreButynski وBarryvdh أكثر قابلية للقراءة من اقتراحي ، ما تضيفه هذه الإجابة هو بعض الكفاءة.

يقوم باسترداد إدخالات المجموعة الحالية فقط (في الواقع المعرف فقط) وإرفاقها في حالة عدم وجودها. تسترد طريقة المزامنة (حتى بدون فصل) جميع المعرفات المرفقة حاليًا. بالنسبة للمجموعات الصغيرة ذات التكرارات الصغيرة ، سيكون هذا بالكاد فرقًا ، ... تحصل على وجهة نظري.

على أي حال ، فإنه بالتأكيد ليس قابلاً للقراءة ، لكنه يقوم بالخدعة.

if (is_null($book->authors()->find($author->getKey(), [$author->getQualifiedKeyName()])))
    $book->authors()->attach($author);
0
Peter de Kok