Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

sane79's avatar

Eloquent multiple relationship with condition

Hi all, first, sorry for my bad english.

Since two days, I bug on this problem at my work.

I have a mySql DB with 4 tables (old tables with no primary key, but it's not the problem).

My tables :

  • Quiz
  • User
  • Program_society_A
  • Program_society_B

Every User have 1 Quiz, and every User have 1 Program (but on society_A or society_B with the condition in a field "society" in User table)

So, in the controller, I want all the Quiz and I want do relation with user and program.

I do that in controller :

$quizList = QUIZ::with('user.program')->get();

and in the quiz model :

public function user()
{
    return $this->belongsTo('App\Models\User');
}

and in the user model :

public function program()
{
    if ($this->society == 'A') {
        return $this->hasOne('\App\Models\A\Program');
    } elseif ($this->society == 'B') {
        return $this->hasOne('\App\Models\B\Program');
    }
}

but it seems that society does not exist. $thisis null with the relation

And when we look in the debug bar, Laravel do 2 queries separately (one for the relation with inscrit and one for program relation).

I hope you understand what I mean.

0 likes
14 replies
Cinek's avatar

Are you sure that $this->society is always 'A' or 'B' and there are no other values like 'a', 'b' or null?

sane79's avatar

Thanks for your response.

Yes, just 'A' or 'B'

sane79's avatar

I have found a tempory solution, but I think it's not good, with a MySql View wich regroup the 2 tables Program_society_A and Program_society_B.

rawilk's avatar

I've tried this before but had the same problem you were having, so instead (although not the most desirable solution) I made it into an accessor on the model.

1 like
Vilfago's avatar

I think it couldn't work this way, as the data aren't loaded when Eloquent is reading your relations.

It is not better to have 3 Tables Quiz User Program ('id', 'user_id', 'society_id')

and if needed a Society table.

Therefore your relation in user model is just

public function program()
{
        return $this->hasOne('\App\Models\Program');
}
rawilk's avatar

I had a notification model that could apply to three different models: Property, Rental, or Service.

public function getItemAttribute()
{
    switch ($this->type) {
        case 'property':
            return Property::where('id', $this->item_id)->firstOrNew([], ['title' => 'Property']);
        // Same thing for other two
    }
}

// to use it
$notification->item->title;

Looking back at it, I probably could of done it with a Polymorphic relationship, but I didn't think of it at the time.

1 like
sane79's avatar

@Vilfago ok for your first phrase. After, I can't change my MySql DB, it's at my work.

And I know it will be best as you explain.

@wilk_randall thanks, I will see that

sane79's avatar

@wilk_randall , I have test with an accessor and I's not work.

I think it's impossible, as @Vilfago said, the data are not loaded when Eloquent is reading my relation :(

rawilk's avatar

@sane79 - It isn't actually a relation, it's an accessor, so you should have access to the model's data. Can you show your code of how you did it?

1 like
sane79's avatar

when I have an new object User created, it's ok, the accessor work. But I want to have access to the data when I do the relation with the function with('user.program')

Vilfago's avatar

I would say that

 if ($this->society == 'A') {

Could not be interpreted as I guess that when you wrote :

$quizList = QUIZ::with('user.program')->get();

$this->society does not exist.

So I think @wilk_randall is right, you have to use polymorphic. https://laravel.com/docs/5.6/eloquent-relationships#polymorphic-relations

I let you read, because as you cannot change the database, you will have to update your model, but also add a relationship "morph map" in the boot function of one of your provider.

user3008's avatar

you can also load the result first before accessing the prop

public function program()
{
    $this->refresh(); // this will fetch the record from DB

    if ($this->society == 'A') {
        return $this->hasOne('\App\Models\A\Program');
    } elseif ($this->society == 'B') {
        return $this->hasOne('\App\Models\B\Program');
    }
}

Please or to participate in this conversation.