Currently I have a one to many relationship setup. The way it works is one Champion has many Skins.
champions
table has id, champion
skins
table has id, set, champion, skin, champion_id
- The champion
field in this table is redundant, but that's only temporary.
The problem I'm getting is that when I call the skins
table to receive champion name, it throws an error.
Models:
class Champion extends Eloquent {
protected $table = 'champions';
public function skin(){
return $this->hasMany('Skin');
}
}
class Skin extends Eloquent {
protected $table = 'skins';
public function champion() {
return $this->belongsTo('Champion');
}
}
Controller:
$champ = Champion::find(2);
foreach ($champ->skin as $c) {
echo $c->set; //outputs the set for id=2
}
$skin = Skin::all();
foreach ($skin as $s) {
echo $s->champion->champion; //errors out.
echo $s->champion; //outputs all champion names (multiple times, if they have multiple skins).
}
What I want to out put is the Champion name, and then all of the skins the champion has. Perhaps someone can help tell me what's wrong and why this isn't working. I've looked at Laravel eloquent - One to many relationships where essentially is the same thing I'm doing, but still does not work.
Example output:
champion1
skin1
skin2
skin3
champion2
skin1
skin2
Your relations are correct, the controller has flaws.
Problem is that you have a field called champion and the relation has the same name
The only thing I would change is relation name skin
-> skins
to make it verbose.
To make what you need do this:
// Champion model
public function skins()
{
return $this->hasMany('Skin');
}
// controller
$champions = Champion::with('skins')->get(); // with() means eager loading to avoid n+1 issue
@foreach($champions as $champion)
{{ $champion->id }}
@foreach($champion->skins as $skin)
<div> {{ $skin->set }} </div> // or whatever you like here
@endforeach
@endforeach
Now the controller that doesn't work:
$skin = Skin::all();
foreach ($skin as $s) {
echo $s->champion->champion; // $s->champion is a field on skins table
echo $s->champion; // outputs this field value
}
In this situation you can do this (but you'd rather not, rename field or relation instead):
echo $s->champion()->first()->id; // fetch related model and output its property
Your models seem to be setup just fine. Unless you did some non standard things in the database like ommiting an id column, then you might have to specify the primary key and the foreign key on the relation. So the following should work just fine and output what you ara aiming for.
Your query
$champions = Champion::all();
Blade template
@foreach($champions as $champion)
<ul>
<h3>{{$champion->name}}</h3>
@foreach($champion->skin() as $skin)
<li>{{$skin->name}}</li>
@endforeach
</ul>
@endforeach
Use
Skin::with(['champion'])->get();
instead of Skin::all(); to eager load the relationship data.