web-dev-qa-db-fra.com

Vérification de Laravel si le modèle associé existe

J'ai un modèle Eloquent qui a un modèle connexe:

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

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

Lorsque je crée le modèle, celui-ci n’a pas nécessairement de modèle associé. Lorsque je le met à jour, je peux ajouter une option ou non.

Je dois donc vérifier si le modèle associé existe, pour le mettre à jour ou le créer, respectivement:

$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> est le code que je recherche.

107
Tom Macdonald

Dans php 7.2+ vous ne pouvez pas utiliser count sur l'objet relation, il n'y a donc pas de méthode unique pour toutes les relations. Utilisez la méthode de requête à la place de @tremby ci-dessous:

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

solution générique travaillant sur tous les types de relations ( pre php 7.2 ):

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

Cela fonctionnera pour toutes les relations car les propriétés dynamiques renvoient Model ou Collection. Les deux implémentent ArrayAccess.

Alors ça va comme ça:

relations uniques: 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

à-plusieurs relations: 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

Un objet Relation transmet les appels de méthodes inconnus à un constructeur de requêtes Eloquent , configuré pour ne sélectionner que les objets liés. Ce générateur transmet à son tour les appels de méthodes inconnus à its sous-jacent query Builder .

Cela signifie que vous pouvez utiliser les méthodes exists() ou count() directement à partir d'un objet de relation:

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

Notez les parenthèses après relation: ->relation() est un appel de fonction (obtenir l'objet relation), par opposition à ->relation pour lequel un getter de propriétés magiques a été configuré pour vous par Laravel (pour obtenir l'objet/les objets associés).

L'utilisation de la méthode count sur l'objet relation (c'est-à-dire, l'utilisation des parenthèses) sera beaucoup plus rapide que l'exécution de $model->relation->count() ou count($model->relation) (sauf si la relation a déjà été chargée avec impatience) car elle exécute une requête de comptage plutôt que d'extraire toutes les données pour tous les objets liés de la base de données, juste pour les compter. De même, utiliser exists n'a pas non plus besoin d'extraire les données de modèle.

exists() et count() fonctionnent sur tous les types de relation que j'ai essayés, donc au moins belongsTo, hasOne, hasMany et belongsToMany.

55
tremby

Après Php 7.1 , la réponse acceptée ne fonctionnera pas pour tous les types de relations.

En fonction du type de relation, Eloquent renverra un Collection, un Model ou un Null. Et dans Php 7.1 count(null) lancera un error

Donc, pour vérifier si la relation existe, vous pouvez utiliser:

Pour les relations simples: Par exemple, hasOne et belongsTo

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

Pour les relations multiples: Par exemple: hasMany et belongsToMany

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

Pas sûr que cela ait changé dans Laravel 5, mais la réponse acceptée utilisant count($data->$relation) n'a pas fonctionné pour moi, car l'acte même d'accéder à la propriété de relation a provoqué son chargement.

À la fin, un isset($data->$relation) simple a fait l'affaire pour moi.

4
Dave Stewart

Vous pouvez utiliser la méthode relationLoaded sur l'objet de modèle. Cela a sauvé mon bacon alors j'espère que cela aidera quelqu'un d'autre. J'étais vu cette suggestion quand j'ai posé la même question sur Laracasts.

2
Anthony

Comme Hemerson Varela l'a déjà dit dans Php 7.1, count(null) lève une variable error et hasOne renvoie null si aucune ligne n'existe. Puisque vous avez une relation hasOne, j'utiliserais la méthode empty pour vérifier:

$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

Vous avez dit que vous voulez vérifier si la relation existe déjà, vous pouvez donc faire un update ou create. Cependant, cela n'est pas nécessaire, à cause de la méthode updateOrCreate

Faites juste ceci:

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