Laravel चेक यदि संबंधित मॉडल मौजूद है


151

मेरे पास एक एलोकेंट मॉडल है जिसमें एक संबंधित मॉडल है:

public function option() {
    return $this->hasOne('RepairOption', 'repair_item_id');
}

public function setOptionArrayAttribute($values)
{
    $this->option->update($values);
}

जब मैं मॉडल बनाता हूं, तो जरूरी नहीं कि वह संबंधित मॉडल हो। जब मैं इसे अपडेट करता हूं, तो मैं एक विकल्प जोड़ सकता हूं, या नहीं।

इसलिए मुझे यह जांचने की आवश्यकता है कि क्या संबंधित मॉडल मौजूद है, या तो इसे अपडेट करने के लिए, या इसे क्रमशः बनाएं:

$model = RepairItem::find($id);
if (Input::has('option')) {
    if (<related_model_exists>) {
        $option = new RepairOption(Input::get('option'));
        $option->repairItem()->associate($model);
        $option->save();
        $model->fill(Input::except('option');
    } else {
       $model->update(Input::all());
    }
};

<related_model_exists>वह कोड कहां है जिसकी मुझे तलाश है।


3
बहुत बढ़िया सवाल धन्यवाद! और नीचे दिए गए लोगों के लिए महान जवाब। मुझे अपने प्रोजेक्ट पर समय की बचत की।
राफेल

जवाबों:


197

में php 7.2 + आप उपयोग नहीं कर सकते countसंबंध वस्तु पर है, इसलिए कोई भी फिट-सब सब संबंधों के लिए विधि है। नीचे दिए गए @tremby के बजाय क्वेरी विधि का उपयोग करें:

$model->relation()->exists()

सभी संबंधित प्रकारों पर काम करने वाला सामान्य समाधान ( पूर्व php 7.2 ):

if (count($model->relation))
{
  // exists
}

यह हर संबंध के लिए काम करेगा क्योंकि गतिशील गुण वापस आते हैं Modelया Collection। दोनों लागू करते हैं ArrayAccess

तो यह इस प्रकार है:

एकल संबंध: hasOne / belongsTo/ morphTo/morphOne

// no related model
$model->relation; // null
count($model->relation); // 0 evaluates to false

// there is one
$model->relation; // Eloquent Model
count($model->relation); // 1 evaluates to true

कई संबंधों के लिए: hasMany / belongsToMany/ morphMany/ morphToMany/morphedByMany

// no related collection
$model->relation; // Collection with 0 items evaluates to true
count($model->relation); // 0 evaluates to false

// there are related models
$model->relation; // Collection with 1 or more items, evaluates to true as well
count($model->relation); // int > 0 that evaluates to true

1
पढ़िए पूरी बात count($relation)सभी संबंधों के लिए एक सामान्य समाधान है। यह के लिए काम करेंगे Modelऔर Collection, जबकि Modelकोई है ->count()विधि।
जारेक टकाज़ीक

7
@CurvianVynes नहीं, यह नहीं है। Collectionइसकी अपनी विधि है isEmpty, लेकिन जेनेरिक emptyफ़ंक्शन किसी ऑब्जेक्ट के लिए गलत है (इस प्रकार खाली संग्रह के लिए काम नहीं करेगा)।
जारेक टक्कज़ी

1
count($model->relation)morphToजब कोई संबंध अभी तक स्थापित नहीं हुआ था, तो काम नहीं किया । विदेशी आईडी और प्रकार शून्य हैं और लारवेल द्वारा निर्मित db क्वेरी फर्जी है और अपवाद को बढ़ाती है। मैंने $model->relation()->getOtherKey()वर्कअराउंड के रूप में इस्तेमाल किया ।
Jocelyn

1
@ जॉलीकिन हाँ, यह एलिगेंट बग है। दुर्भाग्य से उनमें से कम से कम बहुरूपी संबंधों के लिए कुछ हैं, तो जाहिर है आप उन पर किसी भी तरह से भरोसा नहीं कर सकते।
जारेक टकाज़ी

2
यह PHP 7.2 पर टूट जाएगा, लौटकर:count(): Parameter must be an array or an object that implements Countable
कोडगोडी

81

एक रिलेशन ऑब्जेक्ट एक अज्ञात क्वेरी बिल्डर के माध्यम से अज्ञात विधि कॉल से गुजरता है , जो केवल संबंधित वस्तुओं का चयन करने के लिए सेट किया गया है। वह बिल्डर बदले में अपने अंतर्निहित क्वेरी बिल्डर के माध्यम से अज्ञात तरीके से कॉल करता है ।

इसका अर्थ है कि आप किसी संबंध वस्तु से सीधे exists()या count()विधियों का उपयोग कर सकते हैं :

$model->relation()->exists(); // bool: true if there is at least one row
$model->relation()->count(); // int: number of related rows

इसके बाद कोष्ठकों पर ध्यान दें relation: ->relation()एक फ़ंक्शन कॉल (रिलेशन ऑब्जेक्ट प्राप्त करना) है, ->relationजिसके विपरीत लारवेल द्वारा आपके लिए एक मैजिक प्रॉपर्टी गेट्टर स्थापित किया गया है (संबंधित ऑब्जेक्ट / ऑब्जेक्ट्स प्राप्त करना)।

countसंबंध वस्तु पर विधि का उपयोग करना (यानी, कोष्ठक का उपयोग करना) करने की तुलना में बहुत तेजी से होगा ( $model->relation->count()या count($model->relation)जब तक संबंध पहले से ही लोड नहीं हुआ है) क्योंकि यह किसी भी संबंधित वस्तुओं के लिए डेटा के सभी को खींचने के बजाय एक गणना क्वेरी चलाता है। डेटाबेस से, बस उन्हें गिनने के लिए। इसी तरह, existsमॉडल डेटा को खींचने की जरूरत नहीं है।

दोनों exists()और count(), सभी संबंध प्रकार मैं कोशिश की है पर काम तो कम से कम belongsTo, hasOne, hasMany, और belongsToMany


मौजूद लुमेन में उपलब्ध नहीं है, निश्चित नहीं है कि क्यों।
briankip

@briankip - यह चाहिए। आपको लगता है कि आप संग्रह (जादू संपत्ति का उपयोग करके) के बजाय संबंध वस्तु (विधि को कॉल करके) प्राप्त कर रहे हैं?
कांप

18

मैं existsविधि का उपयोग करना पसंद करता हूं :

RepairItem::find($id)->option()->exists()

यह जाँचने के लिए कि संबंधित मॉडल मौजूद है या नहीं। यह लारवेल 5.2 पर ठीक काम कर रहा है


1
+1; गणना ($ मॉडल-> संबंध) मेरे लिए लारवेल 5.2 में सच हो रहा था, भले ही संबंध तालिका में कोई आइटम नहीं था। -> मौजूद () चाल है।
बेन विल्सन

9

Php 7.1 के बाद , स्वीकृत उत्तर सभी प्रकार के रिश्तों के लिए काम नहीं करेगा।

प्रकार के संबंध निर्भर करते हुए, सुवक्ता एक वापस आ जाएगी Collectionएक, Modelया Null। और Php में 7.1 count(null) एक फेंक देगा error

इसलिए, यह जांचने के लिए कि क्या संबंध मौजूद है आप उपयोग कर सकते हैं:

एकल रिश्तों के लिए: उदाहरण के लिए hasOneऔरbelongsTo

if(!is_null($model->relation)) {
   ....
}

कई रिश्तों के लिए: उदाहरण के लिए: hasManyऔरbelongsToMany

if ($model->relation->isNotEmpty()) {
   ....
}

4

यकीन नहीं होता है कि अगर यह लारवेल 5 में बदल गया है, लेकिन उपयोग किए गए स्वीकृत जवाब count($data->$relation)ने मेरे लिए काम नहीं किया, क्योंकि संबंध संपत्ति तक पहुंचने के बहुत कार्य के कारण इसे लोड किया गया था।

अंत में, एक सीधी-सादी isset($data->$relation)ने मेरे लिए चाल चली।


मेरा मानना ​​है कि यह $data->relationबिना $(6 अक्षरों की सीमा के कारण संपादित नहीं किया जा सकता है)
Zanshin13

2
आह $relationआपके संबंध का नाम होगा, जैसे $data->postsया जैसे। क्षमा करें यदि वह भ्रमित था, तो मैं यह स्पष्ट करना चाहता relationथा कि यह एक ठोस मॉडल संपत्ति नहीं थी: पी
डेव स्टीवर्ट

यह थोड़ी देर के लिए काम कर रहा था, लेकिन मैंने 5.2.29 से 5.2.45 तक लारवेल को अपडेट करने के बाद काम करना बंद कर दिया। किसी भी विचार क्यों या कैसे इसे ठीक करने के लिए? अब यह किसी कारण से संबंधपरक डेटा को लोड करने का कारण बन रहा है।
एंथनी

मैंने एक उत्तर जोड़ा जो इसके लिए एक तय है।
एंथोनी

3

आप संबंध ऑब्जेक्ट पर मॉडल ऑब्जेक्ट का उपयोग कर सकते हैं । इसने मेरी बेकन को बचा लिया, इसलिए उम्मीद है कि यह किसी और की मदद करेगी। मुझे यह सुझाव तब दिया गया जब मैंने लराकोस्ट पर एक ही सवाल पूछा।


2

के रूप में Hemerson वरेला पहले से ही Php 7.1 में कहा count(null)एक फेंक होगा errorऔर hasOneरिटर्न nullअगर कोई पंक्ति मौजूद है। चूंकि आपके hasOneसंबंध हैं, मैं emptyजांचने की विधि का उपयोग करूंगा :

$model = RepairItem::find($id);
if (!empty($temp = $request->input('option'))) {
   $option = $model->option;

   if(empty($option)){
      $option = $model->option()->create();
   }

   $option->someAttribute = temp;
   $option->save();
};

लेकिन यह बहुत ही शानदार है। यह जांचने की कोई आवश्यकता नहीं है कि क्या संबंध मौजूद है, यह निर्धारित करने के लिए कि आपको updateएक createकॉल करना चाहिए या नहीं । बस updateOrCreate विधि का उपयोग करें । यह उपरोक्त के बराबर है:

$model = RepairItem::find($id);
if (!empty($temp = $request->input('option'))) {  
   $model->option()
         ->updateOrCreate(['repair_item_id' => $model->id],
                          ['option' => $temp]);
}

0

जब मैंने गिनती ($ x) फ़ंक्शन के खराब उपयोग के कारण अपने PHP संस्करण को 7.2+ में अपडेट किया तो मुझे अपना कोड पूरी तरह से रिफ्लेक्टर करना पड़ा। यह एक वास्तविक दर्द है और इसके बेहद डरावने भी हैं क्योंकि सैकड़ों परिदृश्य हैं, विभिन्न परिदृश्यों में और कोई भी नियम सभी पर फिट नहीं है।

नियमों का पालन करने के लिए मैं सब कुछ refactor, उदाहरण:

$ x = प्रामाणिक :: उपयोगकर्ता () -> पद-> खोजें (6); (जांचें कि क्या उपयोगकर्ता के पास आईडी = 6 का उपयोग करके -> खोज ())

[FAILS] if(count($x)) { return 'Found'; } 
[GOOD] if($x) { return 'Found'; }

$ x = प्रामाणिक :: उपयोगकर्ता () -> प्रोफ़ाइल-> विभाग; (जांचें कि क्या प्रोफ़ाइल में कुछ विभाग हैं, कई विभाग हो सकते हैं)

[FAILS] if(count($x)) { return 'Found'; }
[GOOD] if($x->count()) { return 'Found'; }

$ x = प्रामाणिक :: उपयोगकर्ता () -> प्रोफ़ाइल-> प्राप्त (); (-> प्राप्त करें () का उपयोग करने के बाद उपयोगकर्ता के पास कोई प्रोफ़ाइल है या नहीं, इसकी जांच करें

[FAILS] if(count($x)) { return 'Found'; }
[GOOD] if($x->count()) { return 'Found'; }

उम्मीद है कि यह मदद कर सकता है, सवाल पूछने के 5 साल बाद भी, इस स्टैकओवरफ्लो पोस्ट ने मुझे बहुत मदद की है!

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.