Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel: belongsToMany() does not get fields in the many-to-many table

Consider the following tables:

user
  id
  name

client
  id
  name

user_client
  user_id
  client_id
  rate
  ...

I want my controller to get all fields in the user table and I also want to list their clients name and rate afterwards. User and Client models:

class User extends Eloquent {

    public function clients()
    {
        return $this->belongsToMany('Client', 'user_client');
    }

}

class Client extends Eloquent {

    public function users()
    {
        return $this->belongsToMany('User', 'user_client');
    }

}

There is no model for user_client.

An extract of my UsersController@show

public function show($username) // foo.com/user/{$username}
{
  $user = User::where('username', '=', $username)->firstOrFail();
  $clients = User::find($user->id)->clients;

  return View::make('users.show', compact('user', 'clients'));
}

While that runs fine, let's look at the view users/show.blade.php:

<h1>{{$user->name}}</h1>
@foreach($clients as $client)
  <p>{{$client->name}}, {{$client->rate}}</p>
@endforeach

$client->rate is undefined. Checking my query debuggers, belongsToMany will only select client.* but it doesn't select anything other than user_id and client_id.

How can I modify User::find($user->id)->clients; so that it will select user_client.* as well?

EDIT: While I'm at it, any suggestions for improvements are also welcome.

like image 475
tiffanyhwang Avatar asked Jan 15 '14 15:01

tiffanyhwang


1 Answers

If you refer to the laravel docs on pivot tables, you will need to add withPivot on your relationships.

In your example you will need to add the following:

class User extends Eloquent 
{

    public function clients()
    {
        return $this->belongsToMany('Client', 'user_client')->withPivot('rate');
    }
}

Update your view like:

<h1>{{$user->name}}</h1>
@foreach($user->clients as $client)
    <p>{{$client->name}}, {{$client->pivot->rate}}</p>
@endforeach

I would also eager load the clients to save you time:

public function show($username) // foo.com/user/{$username}
{
    $user = User::with('clients')->where('username', '=', $username)->firstOrFail();

    return View::make('users.show', compact('user'));
}

Hope that helps :)

like image 173
Cristian Avatar answered Oct 05 '22 23:10

Cristian