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

the_lar's avatar

How do I configure a new model that has many Users?

Hi all,

Quite new to laravel so please bear with me if this is a basic question...

Given that I have already setup Users and am using Spatie to provide my Roles and Permissions, I now want to set up a new model for a Client. A Client can have many Users, so I am guessing this is a hasMany relationship? But a User may only belong to one Client - I do however want the option of a User not belonging to any Client at all, this would be for SuperAdmins.

How do I set this up given that I already have a User model, but I don't have any foreign keys on it for the Client relationship? How do I set it up so that a User doesn't have to be assigned to a Client?

Would appreciate basic instructions and explanations if at all possible... many thanks in advance.

0 likes
15 replies
kokoshneta's avatar

That is indeed a hasMany/belongsTo relationship (one-to-many). Add a client_id column of type foreignId to your user model (using a migration – make sure to make it nullable), then add the appropriate relationship functions to the user and client models, and voilà. That’s all yo need to do.

Assuming you’ve created your client model and the corresponding table, here’s what you do:

1. Create the migration for the relationship

> php artisan make:migration add_client_relation_to_users
// Or whatever you want to call the migration file

2. In the generated migration file, add the foreign ID column

return new class extends Migration {
	public function up() {
		Schema::table('users', function (Blueprint $table) {
			$table->foreignId('client_id')->nullable()->cascadeOnUpdate()->nullOnDelete()->constrained();
			$table->boolean('is_admin')->default(FALSE);
		});
	}

	public function down() {
		Schema::table('users', function(Blueprint $table) {
			$table->dropColumn('client_id');
			$table->dropColumn('is_admin');
		});
	}
};

This will add the column to your users table, make sure it references clients.id, cascade on update (so if for some reason a client’s ID changes, it will be updated in the user table as well), and set to null on delete (so if a client is deleted, the user remains, but becomes disassociated with any client).

(I’ve also added an is_admin column to actively keep track of administrators.)

3. In your models, add the appropriate relationship methods

class User extends Model {
	public function client() {
		return $this->belongsTo(Client::class);
	}
}

class Client extends Model {
	public function users() {
		return $this->hasMany(User::class);
	}
}

That’s it!

the_lar's avatar

Thank you @kokoshneta that's what I was thinking. Can I just check though, given that a User can only belong to one Client (or none), if I was to delete a Client would that automatically delete any Users that belong to it?

kokoshneta's avatar

@the_lar I updated my answer with more details and examples. I assumed you probably don’t want to delete all users associated with a client if you delete the client (you may want to associate them with a different client instead, for example, rather than deleting them), so I’ve set it up so that the foreign ID column is just set to NULL if the client is deleted. If you do want to also delete users, just change nullOnDelete() to cascadeOnDelete().

(If you keep the users around, you should of course make sure that super administrators are defined actively with an is_admin column or similar, not just by having an empty foreign ID – otherwise when you delete a client, all its users would become super admins.)

the_lar's avatar

@kokoshneta that's brilliant, thank you so much for your help, I will go through this in detail tomorrow now but I'm sure I will be able to things working as I need to with this help.

Snapey's avatar

Not sure I agree. This is a case for a many to many relationship and a client_user pivot table

User hasMany Client

Client hasMany User

both should have a belongsToMany relationship with the other model

This is one of those cases where it does not hurt to plan for the inevitable user has relationships with two clients. If your code today only allows one client per user then you can still use the same database structure.

the_lar's avatar

@Snapey I did wonder that, but I think (I'm pretty sure) that in this app, a User will only ever belong to one Client (or not have a Client) in the case of a super admin. I can't really see any scenario where a User could belong to multiple Clients. Would there be any benefit to setting it up this way even if don't foresee a need for it now?

kokoshneta's avatar

@Snapey Depends on what users and clients are. Say clients are banks, for example, and users are employees of these banks. There’s a very good chance you absolutely do not want users to be able to belong to more than one client in that case, because that would likely constitute breach of contract, conflict of interest, corporate espionage or any number of unpleasant things.

the_lar's avatar

@kokoshneta yeah so in this case the app is a management tool for an agency. The agency has Clients and the Client has Users, the User will only belong to a single Client, or will be an agency employee, like an account manager or a freelancer

kokoshneta's avatar

@the_lar If users can be freelancers for clients, it might be possible to have someone who does freelance work for more than one client and needs to use the system on behalf of several clients. That’s common enough with freelancers. If that is the case, then Snapey is right and a many-to-many relationship is what you want.

the_lar's avatar

@kokoshneta ah no, they'd be freelancers for the agency, not the Client... they would work on client jobs but they wouldn't have any explicit relationship to the Client as far as I can foresee. Maybe it is safer to set it up as a many-to-many though. That makes it more complicated though doesn't it?

Snapey's avatar

@the_lar but it then becomes about what you use to identify the user. Ive had stupid situations before where I've had to use different emails for two clients that share the same saas platform, and then remember to login with the right one.

the_lar's avatar

Hi, just picking back up on this. Taking your advice and going with a Many to Many relationship. When I create the migration for the pivot table, how do I ensure that a User does not have to belong to a client? Like for instance, if a Client was deleted, would the client_id column in the pivot table get set to null or would the row itself get deleted? Is there anything special I need to do basically?

This is what I've set my migration to currently:

public function up()
    {
        Schema::create('client_user', function (Blueprint $table) {
            $table->id();
            $table->integer('client_id')->unsigned()->nullable()->cascadeOnUpdate()->nullOnDelete()->constrained();
            $table->integer('user_id')->unsigned()->nullable()->cascadeOnUpdate()->nullOnDelete()->constrained();
        });
    }

But that's using some of the suggestions @kokoshneta made when I was thinking it would be a hasMany relationship. Thanks for your help so far by the way!!

kokoshneta's avatar
Level 27

@the_lar If there’s a pivot table, the foreign key is in that table, so if you cascade on delete, it only affects that row, not the users table; that would be very bad. Imagine if you have a user with two client links, then one of the two clients is deleted – if that deleted the user as well, the other client would suddenly have one of their users deleted for no reason, not good.

Note: the foreign keys in the pivot table should not be nullable. The pivot table represents only a connection between two rows in different tables, nothing else, and if you make one or both of them nullable, it doesn’t really represent anything at all anymore. You can’t represent a connection between A and B if one (or both) of them is empty.

You can think of the pivot table as being sort of like the axle between the wheels of a car: the axle itself is just there to solidify the connection between the two wheels and make sure they move in sync, but if you make the left or right half of the axle optional, you just end up with two separate, unconnected wheels that will fall off the car.

There is no requirement with a many-to-many relationship that users must belong to a client or vice versa; you can add clients and users to your heart’s content without connecting them to each other in any way. Then you can subsequently connect and detach clients and users to and from each other as you wish.

the_lar's avatar

@kokoshneta OK thank you for the explanations, I think I'm getting there.

Would my simplified migration for my pivot table therefore look something like this:

public function up()
    {
        Schema::create('client_user', function (Blueprint $table) {
            $table->id();
            $table->foreignId('client_id');
            $table->foreignId('user_id');
        });
    }

Do I need constrained() also - what does that do?

kokoshneta's avatar

@the_lar The constrained() method just makes sure that Laravel uses its best logic to guess which column in which table the foreign key references, which is something you do want, so add it. It will make sure that ->foreignId('client_id') is taken to mean that client_id references the id column in the clients table.

(And of course, in order to use foreignId(), the ID columns in your user and client tables should also be unsigned bigints, which they are automatically if you use ->id() as you do on the pivot table here – I’m assuming you did the same in the other tables. If the ID columns in those tables aren’t unsigned bigints, you’d have to create the foreign key manually.)

Please or to participate in this conversation.