BENderIsGr8te's avatar

Check if Eloquent Relationship is Empty

I have a project where users can have various different services. Each Service has a separate set of information needed. I have 1 users table and then I have 1 table for each service. In my User model I have a method name for each service that has a hasOne() Eloquent relationship.

Not every user has every service, so I need a way to check something like

$user = User::find(1);
$user->hasMediaProfile();

Then I would have a method that check to see if my Media profile Eloquent Relationship exists. My Model Looks Like this (more or less)

class User extends Model {

   // Extra stuff removed for brevity sake

   public function mediaProfile() 
   {
      return $this->hasOne('App\MediaProfile');
   }
}

The media_profile table has a FK pointing to the User record it belongs to. When I instantiate a user, how can I check to see if that user has a MediaProfile relationship stored in the media_profile table?

Note: First time using syntax highlighting, hopefully I did it right.

0 likes
11 replies
ATOM-Group's avatar
Level 11

Do you need to do this before or after you query the user? That is, do you want to query only users who have mediaProfiles?

If so, you can do this:

User::has('mediaProfile')->get();

If you need to be more specific:

User::whereHas('mediaProfile', function($q) {
     $q->where('some_status', 'whatever'); // in this scope, `$q` refers to the MediaProfile object, not the User.
});

If you need to check whether the user has a media profile after you've already gotten the user, you should simply be able to do:

if (is_null($user->mediaProfile)) { ... }

Since a relation returns null if it can't be found.

11 likes
BENderIsGr8te's avatar

Thanks Tag,

I am actually wanting to check on a user I have already queried. In other words, imagine I am in a blade template and I need to know what profiles they have (in this case mediaProfile) so I know if I should try to display the data from that profile or not for that specific user.

ATOM-Group's avatar

Edited my reply. This should be all that you need to do, since non-existent relations return null.

@if (is_null($user->mediaProfile))
2 likes
BENderIsGr8te's avatar

Hey Tag,

I think you updated your answer while I was typing my previous response. The last option works perfectly when in tinker. I literally tried every check I could think of except is_null(). Live and Learn. Thanks for the quick response!

usman's avatar

@BenderIsGreat I think -- haven't tested -- the @if (is_null($user->mediaProfile)) wont work, since it returns back a Collection and even if the Collection is empty is_null() will always return false use this instead:

//inside App\User:
public function hasMediaProfile(){
    
    return (bool) $this->mediaProfile()->first();
}

And then simply use conditions like:

if($user->hasMediaProfile())//

cc: @tag

4 likes
BENderIsGr8te's avatar

Hey @usman thanks for the heads up. I am heading to bed (late here). In my artisan tinker I did some testing with @tag's suggestion and it was working as expected with a handful of Users that did have the profiles and did not. But when I put it into my project tomorrow if it doesn't work as expected I'll re-visit yours.

FYI, I actually build a hasMediaProfile() function that returns true/false based on whether is_null() comes back true/false.

JohnJones's avatar

Old thread but i think this might be useful for others


// where has relation and key - value
// OR
// doesnt have a relation

->where(function($query){
 $query->whereHas('report', function($q){$q->where('accepted', '<=', '0');})
 ->orWhereHas('report', function($q){$q;}, '<', 1);
})
sogeniusio's avatar

What if you have a one-to-many relationship between model A and model B and you only wanted to return instances of model A if the user_id of model B matched Auth::user->id.

I'm stuck here:

$discussions = Models::discussion()->where(function($query) use ($id) {
      $query->whereHas('post', function($q) use ($id) {
              $q->where('user_id', $id);
      });
});
musheabdulhakim's avatar

If is_null() or empty() is not working for you, you can try using the following:

generic solution working on all the relation types This will work for every relation since dynamic properties return Model or Collection. Both implement ArrayAccess.

if (count($user->mediaProfile))
{
 		// int: number of related rows

}

You can also use this to check if the relationship exist.

$user->mediaProfile()->exists()  // bool: true if there is at least one row
1 like
narendrakumar's avatar

@musheabdulhakim Thanks. It helped me to solve similar issue in my project. It worked. (To admin, I understand it's one year old thread, but still I want stakeholders to know this thread is useful to me)

Please or to participate in this conversation.