Setting up a gaming site. I have 3 tables. A user, rank (think military-ish), and a rank_history table.
Rank:
id, name, abbr, level, nextlevel, mintime
RankHistory:
id, user_id, rank_id, promoter, reason, created_at
public function User()
{
return $this->belongsToMany(User::class);
}
public function PromotedBy()
{
return $this->belongsToMany(User::class, 'rank_history', 'id', 'promoter');
}
public function Rank()
{
return $this->belongstoMany(Rank::class);
}
user:
id, name, yadda (standard user stuff; nothing relevant)
public function RankHistory()
{
return $this->hasMany(RankHistory::class);
}
I use the rank history as a way to set promotions, demotions, and have a history. ultimately I'd love to be able to type $user->rank_detail($detail)
and have it return either the rank's abbr, name, level, whatever.
user.php
protected $with = ['rankhistory'];
public function rank_detail($detail)
{
$rankId = $this->RankHistory->pluck('rank_id')->last();
if (!$rankId) { $rankId = 1;}
return Rank::where('id', $rankId)->value($detail);
}
this works, but it makes a separate query call to hit the Rank table to get the details. Since it's pretty safe I will need the rank info a lot when I get the user, it makes enough sense for me to eager load these. The question is, how? I have tried hasmanythrough
, hasmany
, even tried adding $with =[ rankhistory.rank']
nothing works. I also know this can be solved by adding a rank column to the user table, but where it's possible a user will change rank often, I wanted to keep the user table as clean as possible. Plus having the history table gives the user a record.
So, the question is: what do I need to put on the user (and or other files) to eager load the Rank info with the user?
Also of note, the promoter in the rankhistory table is FK to id on the users table. How would I get that relationship as well? right now I can return $history->promoter and it will give me an id.. how can I get a user info without unnecessary query calls?
Try this:
class User
{
protected $with = ['rankHistory.rank'];
public function rankHistory()
{
return $this->hasOne(RankHistory::class)->latest();
}
public function rank_detail($detail)
{
if ($this->rankHistory) {
return $this->rankHistory->rank->$detail;
}
return Rank::find(1)->$detail;
}
}
class RankHistory
{
public function rank()
{
return $this->belongsTo(Rank::class);
}
}