Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

verism's avatar

How do I set up a One To Many relationship with a pivot (5.4) ?

I'm using the default Authentication functionality in Laravel, and have subsequently added a number of addition user-related tables and relationships. I now need to add a Gender table (with three options: Male, Female and Other) that some - but not all - users will select from.

I believe that I need a One-To-Many set-up for this with a genders_users pivot table (a gender will have many users, but a user my only have one gender), but the documentation only explains pivot tables in a Many-To-Many relationship.

Am I thinking about this in the right way, or is there a simpler solution?

0 likes
6 replies
xmarks's avatar

You do not need a Pivot Table I think. Pivots are for Many-to-Many relations.

In your case you only need 2 tables. users and genders

users table will have gender_id as a Foreign-Key to the genders table.

The relations would be on your User Model:

public function gender() {return $this->belongsTo(Gender::class);}

and on your Gender Model:

public function users() {return $this->hasMany(Users::class);}

You can get the user gender with User::find($id)->gender->name; and so on.

verism's avatar

@xmarks Yeah I'd considered that option, except I'm trying to avoid as many empty fields as possible. Not all users will have to fill in the gender option (I'm not sure what percentage), hence the reason for a pivot.

That said, maybe I'm overthinking it.

xmarks's avatar
xmarks
Best Answer
Level 8

@verism If you are looking for optimization, maybe, I am not certain.

However, you could go with $table->smallInteger('gender_id')->unsigned()->nullable()->default(null); to keep this extra field minimal. (Or even tinyInteger, but this is not supported in all Databases, like PostgreSQL for example will convert it to boolean)

In any case, here it is for manyToMany:

User Model:

public function genders() {return $this->belongsToMany(Gender::class)->withTimestamps();}

On the Gender Model:

public function users() {return $this->belongsToMany(User::class)->withTimestamps();}

You also need a gender_user table with the following:

public function up()
{
    Schema::create('gender_user', function (Blueprint $table) {
        $table->integer('gender_id')->unsigned();
        $table->integer('user_id')->unsigned();
        $table->timestamps();
        
        $table->foreign('gender_id')
          ->references('id')
          ->on('genders')
          ->onUpdate('cascade')
          ->onDelete('cascade');
          
        $table->foreign('user_id')
          ->references('id')
          ->on('users')
          ->onUpdate('cascade')
          ->onDelete('cascade');
    });
}

Notice gender_user is in Alphabetical Order. This is done so laravel can automate a few things for you, otherwise you will need to specify the table names and primary_keys for each table.

Then to attach a Gender to a User: User::find($id)->sync($genderID);

Sync will remove any IDs that are not specified, and attach the specified ones. Like if you had more than 1-gender, then you should pass an array here. It will detach any Genders not present in the Array, and attach the ones that you are passing. If they are already there, it will do nothing. More on this here: Many to Many Relationships and here: Pivot tables and many-to-many relationships

2 likes
jontyjago's avatar

While the documentation explains the pivot functionality using a Many-To-Many example I think it's down to you how you use it. I have a pivot set up for users and roles and whilst I could give each user more than role, in reality I don't and the code limits the ability to add more than one role, so the end result is essentially a One-To-Many.

Obviously each user has exactly one role, so it's not quite the same scenario as yours, but I imagine you can get it work the same way if you apply controls on how many genders can be attached to one user.

It might be overkill but if you don't want to use the BelongsTo and HasMany relationships as @xmarks describes then it would certainly work.

1 like
verism's avatar

@jontyjago I've done exactly the same thing with roles too - although in my case a significant number will have more than one role. I thought perhaps there was a more "correct" way of doing it in a One-ToMany scenario, but you've convinced me otherwise. Definitely overthinking it...

@xmarks Thanks for clarifying those. Of course, I'm now wondering if the first option is just tidier over all... Either way, those two look most viable.

xmarks's avatar

@verism True, I've personally found pivots a bit messy myself. I've only used them for actual many-to-many relations, especially for things like tags, where the tags table would have additional tags added to it by the user as needed (if they are not there, add them, else select the tag).

The problem might be if you will ever need to make complicated queries with gender tables. For example: "List all Posts, made by Male users", i think.

Please or to participate in this conversation.