I have 3 models: Conference
, Session
and Speaker
. A Conference can have many Sessions and many Sessions can have many Speakers.
conferences
-----------
id
name
sessions
--------
id
conference_id
name
session_speaker
---------------
id
session_id
speaker_id
speakers
--------
id
name
I need to write a method which allows me to get all the Speakers of a particular Conference (so all the Speakers from all the Sessions of that particular Conference).
The following illustrates what I think should work, but it obviously doesn't as I can't chain these together.
class Conference extends Eloquent {
public function speakers() {
return $this->hasMany('Session')->belongsToMany('Speaker');
}
}
I have all the Model-Model relationships setup and working correctly (Conference-Sessions, Session-Speakers) however I can't create the bridge between Conference-Sessions-Speakers. Does anyone know how I can achieve this without writing a large SQL join query?
I think if there was a relationship belongsToManyThrough()
this would work however there isn't.
Thanks in advance!
The only difference between hasOne and belongsTo is where the foreign key column is located. Let's say you have two entities: User and an Account. In short hasOne and belongsTo are inverses of one another - if one record belongTo the other, the other hasOne of the first.
with() function is used to eager load in Laravel. Unless of using 2 or more separate queries to fetch data from the database , we can use it with() method after the first command. It provides a better user experience as we do not have to wait for a longer period of time in fetching data from the database.
A one-to-one polymorphic relationship is a situation where one model can belong to more than one type of model but on only one association. A typical example of this is featured images on a post and an avatar for a user. The only thing that changes however is how we get the associated model by using morphOne instead.
Unfortunately, the hasManyThrough relation does not work with many to many relationships in between.
What you can do is something like this:
public function speakers() {
$session_ids = Session::where('conference_id', $this->id);
$speaker_ids = DB::table('session_speaker')->whereIn('session_id', $session_ids)->lists('speaker_id');
return Speaker::whereIn('id', $speaker_ids)->get();
}
You probably need to set the variables to array(0)
if no results are found, otherwise the whereIn function will throw an error.
You could also use an Eloquent-only way, but that would probably result in many more database queries, while this one should be fine with only 2 queries being run.
You can then access the speakers with e.g. Conference::find(1)->speakers()
.
Note from 2021: This answer is from back in 2014 and relates to Laravel 4. Nowadays, this apparently does not work anymore. I would encourage you to check the Laravel docs, maybe this problem can now be solved in a better way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With