it-swarm.com.de

Laravel-Prüfung, wenn verwandtes Modell vorhanden ist

Ich habe ein eloquentes Modell mit einem verwandten Modell:

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

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

Wenn ich das Modell erstelle, hat es nicht unbedingt ein verwandtes Modell. Wenn ich es aktualisiere, kann ich eine Option hinzufügen oder nicht.

Ich muss also prüfen, ob das zugehörige Modell existiert, um es entweder zu aktualisieren oder zu erstellen:

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

Wo <related_model_exists> ist der Code, nach dem ich suche.

107
Tom Macdonald

In php 7.2+ können Sie count nicht für das Beziehungsobjekt verwenden. Es gibt also keine für alle Beziehungen passende Methode. Verwenden Sie stattdessen die Abfragemethode als @tremby:

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

generische Lösung für alle Beziehungstypen (pre php 7.2):

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

Dies funktioniert für jede Beziehung, da dynamische Eigenschaften Model oder Collection zurückgeben. Beide implementieren ArrayAccess.

So geht es so:

Einzelbeziehungen:hasOnebelongsTo/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

_/zu-viele-Beziehungen: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
146
Jarek Tkaczyk

Ein Relation-Objekt leitet unbekannte Methodenaufrufe an einen Eloquent query Builder weiter, der nur die zugehörigen Objekte auswählen kann. Dieser Builder leitet wiederum unbekannte Methodenaufrufe an its unter Abfrage-Generator weiter.

Das heißt, Sie können die Methoden exists() oder count() direkt aus einem Beziehungsobjekt verwenden:

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

Beachten Sie die Klammern hinter relation: ->relation() ist ein Funktionsaufruf (holt das Beziehungsobjekt), im Gegensatz zu ->relation, den ein von Laravel für Sie erzeugter magischer Eigenschafts-Getter (das zugehörige Objekt/die zugehörigen Objekte) eingerichtet hat.

Die Verwendung der Methode count für das Relationsobjekt (d. H. Die Klammern) ist viel schneller als das Ausführen von $model->relation->count() oder count($model->relation) (es sei denn, die Relation wurde bereits geladen), da eine Zählabfrage ausgeführt wird, anstatt alle Daten abzurufen alle zugehörigen Objekte aus der Datenbank, um sie nur zu zählen. Ebenso muss mit exists keine Modelldaten abgerufen werden.

Sowohl exists() als auch count() funktionieren für alle Relationstypen, die ich ausprobiert habe, also zumindest belongsTo, hasOne, hasMany und belongsToMany.

55
tremby

Ich bevorzuge die Methode exists:

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

um zu überprüfen, ob ein verwandtes Modell existiert oder nicht. Es funktioniert gut auf Laravel 5.2

18
Hafez Divandari

Nach Php 7.1 , Die akzeptierte Antwort funktioniert nicht für alle Arten von Beziehungen.

Je nach Typ der Beziehung gibt Eloquent ein Collection, ein Model oder Null zurück. Und in Php 7.1 count(null) wird eine error ausgelöst. 

Um zu prüfen, ob die Beziehung existiert, können Sie Folgendes verwenden:

Für einzelne Beziehungen: Zum Beispiel hasOne und belongsTo

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

Für mehrere Beziehungen: Zum Beispiel: hasMany und belongsToMany

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

Ich bin nicht sicher, ob sich dies in Laravel 5 geändert hat, aber die akzeptierte Antwort mit count($data->$relation) hat für mich nicht funktioniert, da der Zugriff auf die Relationseigenschaft das Laden veranlasst hat.

Am Ende hat eine einfache isset($data->$relation) den Trick für mich gemacht.

4
Dave Stewart

Sie können die Methode relationLoaded für das Modellobjekt verwenden. Das hat meinen Speck gerettet, also hoffentlich hilft es jemand anderem. Ich erhielt diesen Vorschlag gegeben als ich dieselbe Frage an Laracasts stellte.

2
Anthony

Wie Hemerson Varela bereits in Php 7.1 gesagt hat, wirft count(null) eine error und hasOne gibt null zurück, wenn keine Zeile vorhanden ist. Da Sie eine hasOnerelation haben, würde ich die empty-Methode verwenden, um Folgendes zu überprüfen:

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

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

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

Sie sagten, Sie möchten prüfen, ob die Relation bereits existiert, also können Sie eine update oder create ausführen. Dies ist jedoch aufgrund der Methode updateOrCreate nicht erforderlich. 

Mach einfach das:

$model = RepairItem::find($id);
$model->option()
      ->updateOrCreate(['repair_item_id' => $model->id],['option' => 'A']);
0
Adam