2
votes

Let me show the scenario here from the Laravel doc: relevant database tables are users, roles and role_users. Table names are self explanatory.

User model:

class User extends Model
{
    /**
     * The roles that belong to the user.
     */
    public function roles()
    {
        return $this->belongsToMany('App\Role');
    }
}

The doc goes on to say :

As mentioned previously, to determine the table name of the relationship's joining table, Eloquent will join the two related model names in alphabetical order. However, you are free to override this convention. You may do so by passing a second argument to the belongsToMany method:

return $this->belongsToMany('App\Role', 'role_user');

Then it defines the inverse of the relationship :

Role model:

class Role extends Model
{
    /**
     * The users that belong to the role.
     */
    public function users()
    {
        return $this->belongsToMany('App\User');
    }
}

Then it says :

Since we're reusing the belongsToMany method, all of the usual table and key customization options are available when defining the inverse of many-to-many relationships.

What I understand so far:

The pivot table has been defines in User model and the docs says that
all of the usual table and key customization options are available in Role model with inverse of many-to-many relationships.

So it seems there is also the option to define the pivot table in Role model as well .

Eloquent will join the two related model names in alphabetical order to define the pivot table name by default.

On which model should I define the pivot table when the pivot table name is not according to the default convention ?

3
You should pass the pivot table (non conventional) name as second argument when you define the belongsToMany relationship in both models - porloscerros Ψ

3 Answers

0
votes
/**
* On the User model
*/
public function roles()
{
    return  $this->belongsToMany('App\Role', 'role_users', 'user_id', 'role_id')->withTimestamps();
}


/**
* On the roles model
*/
public function users()
{
    return  $this->belongsToMany('App\Role', 'role_users', 'role_id', 'user_id')->withTimestamps();
}

Where role_users is the pivot table ,and first argument is foreignPivotKey second argument is relatedPivotKey

In this way you have a full relation on both models.. you can access all user roles and viceversa

0
votes

Define them on both. Both User and Role use the belongsToMany() relation which indicates a many-to-many relation.

The function looks like this:

public function belongsToMany($related, $table = null, $foreignPivotKey = null, $relatedPivotKey = null,
                                  $parentKey = null, $relatedKey = null, $relation = null)

so

$this->belongsToMany(User::class, 'role_user');
// and
$this->belongsToMany(Role::class, 'role_user');

So you can just define the $table parameter in both relations. It is also the better way to do this in my opinion, since this magical guessing of the table name can cause confusion.

0
votes

Try Switching the Eloquent Relationship in the Models this way. But first of all, make sure you use the models, i.e


/**
* On the User model
*/
use App\Role;

public function roles()
{
    return  $this->belongsToMany(Role::class, 'role_users', 'user_id', 'role_id')->withTimestamps();
}

/** where user_id is the primary key in the table referencing the User model and the role_id is the equivalent in the Referenced/Foreign table. 
**[I know you understand what I mean here.]** -- Same thing applies to the code in the Role Model
 **/



/**
* On the roles model
*/

use App\User;

public function users()
{
    return  $this->HasMany(User::class, 'role_users', 'role_id', 'user_id')->withTimestamps();
}`

I hope i didn't misinterpret your question.