13en's avatar
Level 2

Getting Relational Data in foreach

So i have this index page which shows a collection of monsters (similar to a Ecommerce index page)

I also however have an adopt table where users can adopt monsters and update their name so need to display the latest name from the adopts table instead of the name from the monsters table if that makes sense in the foreach?

Relationships are

User Model

public function adopts()
{
    return $this->hasMany(Adopt::class);
}

Adopts Model

    public function monster()
  {
  return $this->belongsTo(Monster::class);
  }

 public function user()
 {
   return $this->belongsTo(User::class);
  }

Monster model

public function adopts()
   {
  return $this->hasOne(Adopt::class);
  }

 public function users()
  {
    return $this->hasOne(user::class);
  }

And finally the tables are setup like

Users table name | email | score | password

Monsters table hidden | name | description | cost | backgroundcolor | image

Adopts table name | user_id | message | adlink | cost |approved | monster_id

Any help would be much appreciated

0 likes
1 reply
Snapey's avatar
Snapey
Best Answer
Level 122

I assume only adopts record is valid for a monster. I Assume you keep the old records around?

create an adopted relationship on monster?

Monster model

public function adopted()
{
    return $this->hasOne(Adopt::class)->latest()->first();

    //assuming model has timestamps
}

You should then be able to do $monster->adopted->name

but since the monster might not be adopted, you should adapt the name attribute on the monster with an accessor;

Monster.php

public function getNameAttribute()
{
    if(!$this->relationLoaded('adopted'))
    {
        $this->load('adopted');
    }

    return $this->adopted->name ?? $this->name;
}

now you can just use $monster->name and you will get the adopted name or the original name if not adopted

if you have multiple adopt records for the same monster and you want to show the history then your existing adopts should be changed to a has many, and probably throw an orderBy on the end.

Please or to participate in this conversation.