Search code examples
laravelrelationshiplaravel-7laravel-8laravel-relations

Laravel API JSON customization and table relationship


I'm developing a social media project using Laravel. I need to provide a customized API for Follows and Followers. Accordingly, I want to establish a relationship between the user table and the followers and followed tables. I have looked at a lot of resources but get confused. Can anyone help me with relationships?

Models

Users: id, username, email, password

Follows: id, user_id, follow_id(user_id)

Followers: id, user_id, follower_id(user_id)

API Url: http://localhost/api/follows/user_id/1

FollowController

public function user_follow($user_id)
{
    $user_find = Follows::where("user_id", "=", $user_id)->get();
    
    return response()->json($user_find, 201);
}

Output

[
  {
    "id": 4,
    "user_id": 1,
    "follow_id": 4,
    "created_at": "2020-03-23T15:11:48.000000Z",
    "updated_at": "2020-12-11T11:10:10.000000Z"
  },
  {
    "id": 5,
    "user_id": 1,
    "follow_id": 1,
    "created_at": "2012-08-30T20:16:51.000000Z",
    "updated_at": "2020-12-11T11:10:10.000000Z"
  }
]

API that brings relevant followed people according to user request. But here, I want to give additional user information of the relevant users, how do I do this?


Solution

  • The most right implementation for me looks like this:

    First you do not need two separate tables for tracking follow actions. With one table you can have both.

    users
    *id
    *username
    *email
    *password
    
    user_followers
    *id
    *user_id
    *follower_id
    

    Then in the model you can do something like:

    public function followers()
    {
        return UserFollower::where('user_id', $this->id)->get();
    }
    
    public function following()
    {
        return UserFollower::where('follower_id', $this->id)->get();
    }
    
    public function followUser($userId)
    {
        // create & insert new row as a follower to the other user
        $follower = new UserFollower();
        $follower->user_id = $userId;
        $follower->follower_id = $this->id;
        $follower->save();
    }
    

    And in the API you can do:

    domain/api/users/{user_id}/followers/
    domain/api/users/{user_id}/following/
    

    • To get additional information from the related model, I think you could do a 'leftJoin'.

    Something like that

    public function followers()
    {
        return DB::table('user_followers')
            ->select('user_followers.*', 'users.email', 'users.name')
            ->where('user_followers.user_id', '=', $this->id)
            ->leftJoin('users', 'user_followers.follower_id', '=', 'users.id')
            ->get();
    }
    

    Edit: Another approach for the followers method is to use the 'hasManyThrough' method of the base Model's class.

    public function followers()
    {
        return $this->hasManyThrough(UserFollower::class, User::class);
    }
    

    This way this method returns User models