İlgili Model Varsa Laravel Kontrolü


156

İlgili bir modele sahip bir Eloquent modelim var:

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

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

Modeli oluşturduğumda mutlaka ilişkili bir modele sahip olmuyor. Onu güncellediğimde bir seçenek ekleyebilir veya eklemeyebilirim.

Bu nedenle, sırasıyla güncellemek veya oluşturmak için ilgili modelin var olup olmadığını kontrol etmem gerekiyor:

$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>Aradığım kod nerede .


3
Harika soru teşekkür ederim! Ve aşağıdaki adamlara harika cevaplar. Projemde bana zaman kazandırdı.
Rafael

Yanıtlar:


206

Gelen php 7.2+ sen kullanamaz countnedenle tüm ilişkiler için kimse uyan tüm yöntem var, ilişki nesne üzerinde. Aşağıda sağlanan @tremby yerine sorgu yöntemini kullanın:

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

tüm ilişki türleri üzerinde çalışan genel çözüm ( pre php 7.2 ):

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

Bu, dinamik özellikler Modelveya döndüğünden beri her ilişki için çalışacaktır Collection. Her ikisi de uygular ArrayAccess.

Yani şöyle:

tek ilişkiler: 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

birçok ilişkiye: 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
Her şeyi okuyun. count($relation)tüm ilişkiler için genel bir çözümdür. Bu için çalışacak Modelve Collectionsüre, Modelhiçbir sahiptir ->count()yöntemi.
Jarek Tkaczyk

8
@CurvianVynes Değil, değil. Collectionkendi yöntemine sahiptir isEmpty, ancak genel emptyişlev bir nesne için yanlış döndürür (bu nedenle boş koleksiyon için çalışmaz).
Jarek Tkaczyk

1
count($model->relation)morphToilişki henüz kurulmamışsa üzerinde çalışmadı . Yabancı kimlik ve tür null ve Laravel tarafından oluşturulan db sorgusu sahte ve istisna yükseliyor. $model->relation()->getOtherKey()Geçici çözüm olarak kullandım .
Jocelyn

1
@Jocelyn Evet, Eloquent hatası. Ne yazık ki, polimorfik ilişkiler için en azından birkaç tane var, bu yüzden açıkçası onlara hiçbir şekilde güvenemezsiniz.
Jarek Tkaczyk

2
PHP 7.2'de kırılacak ve geri dönecek:count(): Parameter must be an array or an object that implements Countable
CodeGodie

85

Bir İlişki nesnesi , bilinmeyen yöntem çağrılarını yalnızca ilgili nesneleri seçecek şekilde ayarlanmış bir Eloquent sorgu Oluşturucu'ya iletir . Builder Bu da, üzerine bilinmeyen bir yöntem çağrıları geçirir onun altında yatan sorgusu Oluşturucu .

Bu, exists()veya count()yöntemlerini doğrudan bir ilişki nesnesinden kullanabileceğiniz anlamına gelir :

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

Bundan sonraki parantezlere dikkat edin relation: ->relation()bir işlev çağrısıdır (ilişki nesnesini alır), bunun tersine ->relationLaravel tarafından sizin için bir sihirli özellik alıcısının ayarladığı (ilgili nesneyi / nesneleri alır).

Kullanılması count(parantez kullanıyor) ilişkisi nesne üzerinde yöntem çok daha hızlı yapmaktan daha olacak $model->relation->count()veya count($model->relation)o ishal beri (ilişki zaten istekli yüklü olmuştur sürece) bir sayım sorgu yerine ilgili herhangi nesneler için tüm verileri çekerek daha veritabanından, sadece saymak için. Aynı şekilde, kullanmanın existsda model verilerini çekmesi gerekmez.

Hem exists()ve count()ben denedim tüm ilişki türleri hakkında, işleri, en azından belongsTo, hasOne, hasMany, ve belongsToMany.


var lümen olarak mevcut değil, neden emin değilim.
briankip

@briankip - olmalı. Koleksiyon yerine (sihirli özelliği kullanarak) ilişki nesnesini (yöntemi çağırarak) aldığınızdan emin misiniz?
tremby

En azından Laravel 6.x'te existsvar olmayan bir morphToilişki için çalışmıyor. SQL hatası alıyor.
Charles Wood

Çağrının exists()ve count()ilişkinin ilgili modelin veritabanına önceden kaydedilmiş olmasını gerektirdiğini unutmayın . İlgili model kaydedilmeden önce var olup olmadığını kontrol etmeniz gerekiyorsa (örneğin, setRelation kullandıysanız), o zaman is_nullveya kullanmalısınız empty.
alexw

19

existsYöntem kullanmayı tercih ederim :

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

ilgili modelin var olup olmadığını kontrol etmek için. Laravel 5.2'de iyi çalışıyor


1
+1; ilişki tablosunda hiçbir öğe olmamasına rağmen, Laravel 5.2'de sayı ($ model-> ilişki) benim için doğru olarak dönüyordu. -> var () hile yapıyor.
Ben Wilson

10

Php 7.1'den sonra , kabul edilen cevap her türlü ilişki için çalışmayacaktır.

İlişkinin türüne bağlı olarak, Eloquent a Collection, a Modelveya döndürecektir Null. Ve Php 7.1'de count(null) bir error.

Dolayısıyla, ilişkinin var olup olmadığını kontrol etmek için şunları kullanabilirsiniz:

Tek ilişkiler için: Örneğin hasOnevebelongsTo

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

Çoklu ilişkiler için: Örneğin: hasManyvebelongsToMany

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

4

Laravel 5'te bunun değişip değişmediğinden emin değilim, ancak count($data->$relation)ilişki özelliğine erişme eylemi yüklenmesine neden olduğu için kabul edilen yanıt benim için işe yaramadı.

Sonunda, basit bir isset($data->$relation)hile benim için hile yaptı.


Biz her zaman bizim $data->relationolmadan $(, olamaz düzenleme nedeniyle 6 karakter sınırı)
Zanshin13

2
Ah, akrabanızın $relationadı $data->postsveya benzeri olabilir. Kafa karıştırıcı olsaydı Üzgünüm, ben temizlemek olduğunu yapmak istedim relationsomut bir modeli özellik değildi: P
Dave Stewart

Bu bir süredir çalışıyordu, ancak Laravel'i 5.2.29'dan 5.2.45'e güncelledikten sonra çalışmayı bıraktı. Neden veya nasıl düzeltileceğine dair bir fikriniz var mı? Artık ilişkisel verilerin herhangi bir nedenle yüklenmesine neden oluyor.
Anthony

Bunun için düzeltmesi olan bir cevap ekledim.
Anthony


3

Hemerson Varela'nın Php 7.1'de söylediği gibi, satır yoksa count(null)bir atar errorve hasOnedöner null. Bir hasOneilişkiniz emptyolduğundan kontrol etmek için yöntemi kullanırdım:

$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();
};

Ancak bu gereksizdir. updateBir createarama veya arama yapmanız gerekip gerekmediğini belirlemek için ilişkinin var olup olmadığını kontrol etmeye gerek yoktur . Sadece updateOrCreate yöntemini kullanın . Bu, yukarıdakine eşdeğerdir:

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

1

Count ($ x) işlevinin kötü kullanımı nedeniyle PHP sürümümü 7.2+ sürümüne güncellediğimde kodumu tamamen yeniden düzenlemek zorunda kaldım. Bu gerçek bir acı ve aynı zamanda son derece korkutucu çünkü farklı senaryolarda yüzlerce kullanım var ve herkese uyan tek bir kural yok ..

Her şeyi yeniden düzenlemek için izlediğim kurallar, örnekler:

$ x = Auth :: user () -> gönderiler-> bul (6); (kullanıcının bir gönderi kimliği olup olmadığını kontrol edin = 6 -> find ())

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

$ x = Auth :: user () -> profil-> departmanlar; (profilde bazı departmanlar olup olmadığını kontrol edin, birçok departman olabilir)

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

$ x = Auth :: user () -> profil-> get (); (a -> get () kullandıktan sonra kullanıcının bir profili olup olmadığını kontrol edin)

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

Bunun yardımcı olabileceğini umuyoruz, soru sorulduktan 5 yıl sonra bile, bu yığın aşımı yazısı bana çok yardımcı oldu!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.