Laravel Check if a sibling model exists

I have an Eloquent model that has an associated model:

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

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

So I need to check if a related model exists, update or create it accordingly:

 $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'm looking for.

+115
php eloquent laravel laravel-5 laravel-4
May 28 '14 at 11:35
source share
8 answers

In php 7. 2+, you cannot use count for a relationship object, so there is no universal method for all relationships. Instead, use a query method like @tremby below:

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



universal solution that works with all types of relations ( pre php 7.2 ):

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

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

So it looks like this:

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

relationship to many: hasMany / belongs to 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 
+150
May 28 '14 at 12:45
source share

A binding object passes unknown method calls through a query request that is configured only to select related objects. This Builder, in turn, passes unknown method calls to its base query designer .

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

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

Pay attention to the parentheses after relation : ->relation() is a function call (getting the relation object), unlike ->relation , which Largvel created for you (getting the associated object / object).

Using the count method of a relationship object (i.e. using parentheses) will be much faster than doing $model->relation->count() or count($model->relation) (unless the relation has already been loaded), as it starts the counter instead of pulling all the data for any related objects from the database, just to count them. Similarly, when using exists no need to output model data.

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

+59
Jun 23 '15 at 23:41
source share

I prefer to use the exists method:

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

to check if the corresponding model exists or not. It works great on Laravel 5.2

+16
Jun 11 '16 at 18:43
source share

After Php 7.1, the accepted answer will not work for all relationship types.

Because depending on the type of relationship, Eloquent returns a Collection , Model or Null . And in Php 7.1, count(null) will give an error .

So, to check if a relation exists, you can use:

For single relationships: e.g. hasOne and belongsTo

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

For multiple relationships: For example: hasMany and belongsToMany

 if ($model->relation->isNotEmpty()) { .... } 
+7
Mar 02 '18 at 23:46
source share

I'm not sure if this has changed in Laravel 5, but the accepted answer using count($data->$relation) did not work for me, since the act of accessing the property of the relation itself caused it to load.

In the end, a simple isset($data->$relation) helped.

+4
Mar 01 '16 at 1:40
source share

You can use the Loaded relation method for the model object. It saved my bacon, so hopefully it helps someone else. I was given this suggestion when I asked the same question about Laracasts.

+2
Oct 26 '16 at 7:12
source share

As Hemerson Varela already said in Php 7.1, count(null) will return an error and hasOne will return null if the row does not exist. Since you have a hasOne relation hasOne I would use the empty method to check:

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

But this is superfluous. There is no need to check if a connection exists to determine if you should update or create call. Just use the updateOrCreate method. This is equivalent to the above:

 $model = RepairItem::find($id); if (!empty($temp = $request->input('option'))) { $model->option() ->updateOrCreate(['repair_item_id' => $model->id], ['option' => $temp]); } 
+2
Apr 26 '18 at 12:29
source share

You said you want to check if the relation exists, so you can update or create . However, this is not necessary due to the updateOrCreate method.

Just do it:

 $model = RepairItem::find($id); $model->option() ->updateOrCreate(['repair_item_id' => $model->id],['option' => 'A']); 
0
Aug 02 '18 at 8:41
source share



All Articles