Laravel Check If Related Model Exists

164

I have an Eloquent model which has a related model:

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

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

When I create the model, it does not necessarily have a related model. When I update it, I might add an option, or not.

So I need to check if the related model exists, to either update it, or create it, respectively:

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

Where <related_model_exists> is the code I am looking for.

This question is tagged with php laravel laravel-4 eloquent laravel-5

~ Asked on 2014-05-28 11:35:12

The Best Answer is


221

In php 7.2+ you can't use count on the relation object, so there's no one-fits-all method for all relations. Use query method instead as @tremby provided below:

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

generic solution working on all the relation types (pre php 7.2):

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

This will work for every relation since dynamic properties return Model or Collection. Both implement ArrayAccess.

So it goes like this:

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

to-many 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

~ Answered on 2014-05-28 12:45:19


89

A Relation object passes unknown method calls through to an Eloquent query Builder, which is set up to only select the related objects. That Builder in turn passes unknown method calls through to its underlying query Builder.

This means you can use the exists() or count() methods directly from a relation object:

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

Note the parentheses after relation: ->relation() is a function call (getting the relation object), as opposed to ->relation which a magic property getter set up for you by Laravel (getting the related object/objects).

Using the count method on the relation object (that is, using the parentheses) will be much faster than doing $model->relation->count() or count($model->relation) (unless the relation has already been eager-loaded) since it runs a count query rather than pulling all of the data for any related objects from the database, just to count them. Likewise, using exists doesn't need to pull model data either.

Both exists() and count() work on all relation types I've tried, so at least belongsTo, hasOne, hasMany, and belongsToMany.

~ Answered on 2015-06-23 23:41:43


Most Viewed Questions: