I wonder if anyone can help, as I\'ve hit a wall and still learning Laravel ORM. Can anyone explain why, when I run:
public function locationTags(){
retu
I'm sorry but you've gone a little sideways here. The relationship definition should just define the Relationship. It's a powerful feature that supports many other aspects of the ORM. What you've done here is more or less build a custom Query, severely limiting the effectiveness of the relationship.
Up until recently, the proper way would have looked something like this.
// class User
public function userHasLocationTags() {
$this->hasMany('App\UserHasLocationTags', 'user_id');
}
// class UserHasLocationTags
public function locationTags() {
$this->hasMany('App\LocationTags', 'location_tag_id');
}
And you would eager load all the results like this.
$user = User::where('id', 1)->with('userHasLocationTags.locationTags')->first();
The code above produces in 3 queries. One to get the User, one to get all the UserHasLocationTags and a one to get all the LocationTags. This may seem wasteful on first blush but consider the following.
$users = User::take(100)->with('userHasLocationTags.locationTags')->get();
Again, this is only 3 queries but now you have loaded 100 users with all their location tags.
But I can see you are a man with an eye for efficiency, and loading all the intermediate relationships and the whole nested hierarchy probably doesn't sit well with you. Well good news! Laravel 5 has added another relationship type for just this situation. hasManyThrough (scroll down a bit to find it).
Has Many Through
The "has many through" relation provides a convenient short-cut for accessing distant relations via an intermediate relation. For example, a Country model might have many Post through a User model.
So in your case it may look something like this...
// class User
public function locationTags()
{
return $this->hasManyThrough('App\LocationTags', 'App\UserHasLocationTags');
}
$users = User::take(100)->with('locationTags')->get();
So now we are down to two queries. If you feel the need to optimize this further and only select specific columns, you can modify the eager load.
$users = User::take(100)->with(['locationTags' => function ($query)
{
$query->select('user_id', 'name', 'location_tag_id');
})->get();
And if you do that frequently, you should wrap it up in a scope.