user4796879
user4796879

Reputation:

Laravel User Has Many User class

I am wondering about the following use case and the simplest, most elegant way to achieve this in Laravel.

Basically I will have a users table

id, name, email, password

I will also create a SuggestedUser model in order to suggest users that a user would like to follow with a reason why they should follow this user.

id user_id, suggested_id, reason

On my users class it is simple enough to associate these two

    public function suggestedUsers()
    {
        return $this->hasMany(SuggestedUser::class);
    }

So now I am able to do

$user->suggestedUsers and get the results of the pivot table

=> Illuminate\Database\Eloquent\Collection {#1881
     all: [
       App\Models\PartnerSuggestion {#1939
         id: 1,
         user_id: 1,
         partner_id: 86,
         reason: "You liked similar posts",
         created_at: null,
         updated_at: null,
       },
     ],
   }

But what I am actually looking to do is to return a collection of User::class from this instead of the collection of the pivot.

so that when I execute $user->suggestedUsers, I would get something like this Including the reason

Illuminate\Database\Eloquent\Collection {#1940
     all: [
       App\Models\User {#1941
         id: 86,
         first_name: "Eugene",
         last_name: "Simonis",
         reason: "You liked similar posts"
       },
       App\Models\User {#1942
         id: 95,
         first_name: "Wilfred",
         last_name: "Stamm",
         reason: "They viewed your profile"

       },
     ],
   }

My question really is what would the cleanest and most elegant way to do this be? Would I need to get rid of the pivot table and make a relationship that references itself? I have looked into packages such as baum but for reasons (last active 4 years ago) I would rather do this without a package

Upvotes: 0

Views: 1634

Answers (2)

Karol Sobański
Karol Sobański

Reputation: 434

In my opinion, you are overcomplicating things. It might be, that you do not need a whole model to solve your problem.

What you actually want to achieve, is Many-to-Many relationship with User model on both sides.

This kind of a relationship in Laravel is referenced with the following inside User model:

public function usersIsSuggestedTo() {
    return $this->belongsToMany(User::class, 'suggested_user', 'suggested_id', 'user_id');
}

public function suggestedUsers() {
    return $this->belongsToMany(User::class, 'suggested_user', 'user_id', 'suggested_id');
}

You also need to create migration for the suggested_user table.

Then, you are accessing the collection of suggestedUsers with $user->suggestedUsers and the pivot table (this is the table joining them) with $user->suggestedUsers->pivot.

Getting reason in your queried collection

You can also append the reason field to your relationship using ->withPivot('reason') on your relationships like following:

return $this->belongsToMany(User::class, 'suggested_user', 'user_id', 'suggested_id')->withPivot('reason');

-

This is the case, when you don't need to have the whole model, e.g. when you use the suggested user table only for storing the reason field and relation itself.

This link to the official documentation might be helpful for you: https://laravel.com/docs/7.x/eloquent-relationships#many-to-many

Upvotes: 1

user4796879
user4796879

Reputation:

I managed to solve the issue by using a polymorphic relationship and a trait.

trait HasSuggestions
{
    public function suggestions()
    {
        return $this->morphMany(PartnerSuggestion::class, 'user');
    }

    public function suggest(Model $suggestedUser)
    {

        $suggestion = (new UserSuggestion())->fillSuggestion($suggestedUser)->fill([
            'reason' => 'reason',
        ]);
        $this->suggestions()->save($suggestion);
        return $suggestion;
    }
}

then in my DB instead of just id fields i use morph fields

$table->morphs('user');
$table->morphs('suggested_user');

by using this trait I still get the same results back but I can now add a new method onto it that would use the query builder so I am able to create a lot of queries

eg:

$user->getSuggested
$user->getSuggestedByDate

etc

Upvotes: 1

Related Questions