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

callumcarlstrom's avatar

Laravel Eloquent followers relationship

Hello! I'm having trouble with an Eloquent relationship. I have a users table with the associated User model, as well as a followers table with the associated Follower model.

users table id name username

followers table id follower_id following_id

User Model

      public function followers(){
        return $this->hasMany('App\Follower', 'follower_id');
    }

    public function followings(){
        return $this->hasMany('App\Follower', 'following_id');
    } 

Follower Model

    public function user(){
        return $this->belongsTo('App\User', 'id');
    }

Both the follower_id and following_id are foreign keys on the id column in users table. I'm trying to retrieve a list of names that are either followers of a particular user, or that a particular user is following. Something like this: $following->user->name. What I want here is to be able to take the follower_id or following_id and identify what name in the users table that is related to. I have tried so many different variations but it always keeps throwing me an error that I'm trying to get data of non-object or that it doesn't exist on this collection instance. Please please help. I have basically lived in the Laravel docs the past few days and I just don't know what I'm doing wrong or what I have to change. Thank you!

0 likes
26 replies
Snapey's avatar

I would tackle this differently by creating a follows_users pivot table and no model. columns of user_id and follower_id

This requires belongsToMany relationships

public function followers()
{
    return $this->belongsToMany(User::class, 'follows_users', 'follower_id', 'user_id');
}

public function followings()
{
    return $this->belongsToMany(User::class, 'follows_users', 'user_id', 'follower_id');
}

but i've not tested this and may well have the keys swapped

samirapadidar's avatar

@Snapey please answer this question:

According to your answer, table should be as follows

| user_id | follower_id|
|--------|--------------|

So if the user with ID 1 follows the user with ID 2

How should this table be filled?

pettturu's avatar

I would probably go this way:

Followers are Users, right? Maybe don't need an own model for those. (Or you can extend one from the User if needed)

No need to add columns to users table, just set up a followings pivot table, having user_id and follower_id.

In User model

public function follows() {

    return User::whereIn('id', \DB::table('followings')->select('user_id')->where('follower_id', $this->id));
}

public function followers() {

    return User::whereIn('id', \DB::table('followings')->select('follower_id')->where('user_id', $this->id));
}

Not tested (may contain typos)... And hopefully I understood your requirements correctly....

tokoiwesley's avatar

Since each User is basically a Follower (can follow another user) and a User can have multiple followers while at the same a Follwer can follow multiple users, I have a working solution for you that I have tested;

users
    id
    name
    username

followers
    id
    user_id

follower_user
    follower_id
    user_id

The follower_user pivot table migration:

Schema::create('follower_user', function (Blueprint $table) {
    $table->bigInteger('follower_id')->unsigned(); // Assuming you have bigIncrements on followers table
    $table->bigInteger('user_id')->unsigned(); // Assuming you have bigIncrements on users table

    $table->foreign('follower_id')
        ->references('id')
                ->on('followers')
                ->onDelete('cascade');

    $table->foreign('user_id')
                ->references('id')
                ->on('users')
                ->onDelete('cascade');

$table->primary(['follower_id', 'user_id']);
});

Here is how your eloquent relationships will look like;

User model class:

public function follower()
{
    return $this->hasOne(Follower::class, 'user_id', 'id');
}

public function followers()
{
    return $this->belongsToMany(Follower::class);
}

Follower model class:

public function user()
{
    return $belongsTo(User::class, 'user_id', 'id');
}

public function users()
{
    return $belongsToMany(User::class);
}

To retrieve followers of a perticular user:

$user->followers;

To retrieve users being followed by a particular follower (user):

$follower->users;

To retrieve the user details (name, username) of a particular follower;

$follower->user;
callumcarlstrom's avatar

@TOKOIWESLEY - Hello!

Thank you very much for this awesome response. So one question though. A user can have many followers and follow many people. Wouldn't the follower method on the User model restrict that with the hasOne attribute??

callumcarlstrom's avatar

@SNAPEY - Hi! Thank you for the reply. As I am a lot less experienced than you, I have a follow-up question to this that may seem obvious to you so I apologize in advance. How do I write the logic in my controller to update/insert rows in the pivot table? Currently, I am using

$follow = new Follower;

and then defining the values I want to input. How do I go about this since there is no model to use for the follows_users pivot table? Thank you!

Snapey's avatar
Snapey
Best Answer
Level 122

I tested this. I think I changed the name of the table slightly, I just did what felt correct

migration:

        Schema::create('follower_user', function (Blueprint $table) {
            $table->unsignedInteger('user_id');
            $table->unsignedInteger('follower_id');
        });

user model;

    public function followings()
    {
        return $this->belongsToMany(User::class, 'follower_user', 'follower_id', 'user_id');
    }

    public function followers()
    {
        return $this->belongsToMany(User::class, 'follower_user', 'user_id', 'follower_id');
    }

php artisan tinker - user 1 gets a new follower 15

 >>> User::find(1)->followers()->attach(User::find(15))  

php artisan tinker - user 1 follows user 7

 >>> User::find(1)->followings()->attach(User::find(7))

You can unfollow with ->detach()

So all that is needed is a pivot table joining users table to users table

4 likes
IanR's avatar

Hi there, i have the exact problem, but im unshure about how to make a "pivot table joining users table to users table".

could you please show an example.

Thank you

Snapey's avatar

(can't believe how convoluted the other replies are!)

2 likes
callumcarlstrom's avatar

@SNAPEY - Just to clarify, are you only using the follower_user table in this case and disregarding the original followers table? I currently have some foreign key assignment that are preventing me from using tinker to test this. I get SQL errors thrown at me.

Snapey's avatar

Yes, just the pivot table follower_user no need for a followers table

3 likes
tokoiwesley's avatar

@CALLUMCARLSTROM - No it won't restrict. The follower method gives you the follower record that belongs to a given user while the followers method gives you the users following the given user.

tokoiwesley's avatar

@snapey your latest solution removes all the complex stuff from my solution. I didn't know it's possible to use a pivot table joining users table to users table. Thanks!

IanR's avatar

Hi there, i have the exact problem, but im unshure about how to make a "pivot table joining users table to users table".

could you please show an example.

Thank you

callumcarlstrom's avatar

@SNAPEY - Thank you for your support. So, just to clarify. The pivot table follower_user needs a foreign key pointing to users table in order to fetch information about each follower? And with this solution, it is possible to fetch followers information from the users table? Thanks again!

callumcarlstrom's avatar

@SNAPEY - I apologize but I do have one more question. Is it not enough to use only one of the two function you provided:

 >>> User::find(1)->followers()->attach(User::find(15))  

or

 >>> User::find(1)->followings()->attach(User::find(7))

Because if I have a foreign key on both user_id and follower_id, both the id's attached in the follower_user table will point to the correct user correct? If I am missing something here, please tell me. As I previously stated, I am still new to this. Thank you sir!

Snapey's avatar

Perhaps this will help. Assume this is the content of the follower_user table

user_id   follower_id
   1         12
   1         17
   1          8
  13          1
  17          1

user 1 is followed by users 12, 17 and 8

user 1 follows 13 and 17

Which column the ID appears in determines if you are following or are followed.

17 follows 1 and 1 follows 17. In this case you might be able to just have one row since they are mutual followers, but for all other cases the relationship is one way. The values in the columns determine the direction of the follow so you need the pivot to store the links and the separately named relationships to know which way around to interpret the columns. This is why they are switched over in the relationship methods.

2 likes
callumcarlstrom's avatar

@SNAPEY - This helped a whole lot! Thank you for clearing that up for me!

Since this is a pivot table and does not have an associated Eloquent model, how would I go about accessing, say the names of each follower from the users table? Something like $follower->user->name. Would I have to bring it in the controller with DB::table('follower_user') and add the appropriate arguments to that?

Snapey's avatar

For the current logged in user (for instance)

Auth::user()->load('followers');

now user has a followers collection, each of which is a user model.

<ul>
  @foreach(Auth::user()->followers as $follower)
    <li>{{ $follower->name }}</li>
  @endforeach
</ul>

load()is the same as with() but for cases where you already have the model

2 likes
callumcarlstrom's avatar

@SNAPEY - Understood! And as for the two attach() on the methods followers and followings, how would you go about writing that in the controller? Putting them both in the same method followUser throws an error since it is trying to insert duplicate rows with the same primary key, id, in follower_user. I tried solving this by only including followers->attach() and then redirecting to another method in the controller with the followings->attach(). The problem I run into is that I am dependent on a variable, $id, from the URL to make the follow work. When I redirect, that variable does not get passed through to the new method. Is there a way around that or is there a way to make it all happen in one method?

Snapey's avatar

no, that does not sound right at all. what you do in the controller is up to you, you should not need to call a different controller

show your code

show your migration, you should not have a primary key on the follower_user table

callumcarlstrom's avatar

@SNAPEY - You're right. It's been updated. The primary keys were a mistake from an old migration. When I do

 $following = Auth::user()->load('followings');

and

@foreach($following as $follow)
                 <h2>Hey I'm a follower!</h2>
 @endforeach

I get three h2's even though there are only two rows in the database.

Snapey's avatar

instead

$following = Auth::user()->followings()->get(); 

since you dont want followings as a child of user

1 like

Please or to participate in this conversation.