DARK MODE 

Posted on Sunday, July 17, 2022 by

Create Instagram Clone with Laravel (Part 14): Create Follow Button with Vue Component Part 2

In this post, I covered from minute 3:33:55 until 3:46:33 of this video.

In previous part, we already made a pivot table to connect Profile and User model. We now need to set up the relationship. 


Set up relationship

We need to define that a user belongs to many profile and a profile belongs to many users. We name the method following and followers respectively.

62
63
64
65
    public function following()
    {
        return $this->belongsToMany(Profile::class);
    }

app > Models > User.php

20
21
22
23
    public function followers()
    {
        return $this->belongsToMany(User::class);
    }
app > Models > Profile.php

Attach and detach relationship

So how do we connect a profile to another profile when a user click the 'Follow' button, and if we click the same button again, it will disconnect? For this, we're going to use Laravel method called toggle. So let's go ahead and open the Follows controller.

We need to return the authenticated user, fetch the following relationship and call the toggle method. What are we toggling (connect/disconnect)? We are toggling the user's profile. Remember, the user that we are referring to in the function is NOT the authenticated user, but the user that is passed into. In below code, is how we use the authenticated user to create that connection with a user's profile.

10
11
12
13
14
    public function store(User $user)
    {
        //Attach and detach user's profile
        return auth()->user()->following()->toggle($user->profile);
    }
app > Http > Controllers > FollowsController.php


You should be getting an alert : 127.0.0.1:8000 says: [object Object]. To see the attach and detach works, let's change alert to console.log in the component (FollowButton.vue). After that, try clicking the button again. 






The first time I click the button, it attach the profile of user with id 2 to user aliya.h, it means that I successfully follow that user. The second time I click, it detach the profile, meaning that I have unfollow it. We can check if the connection is actually created by using tinker.



Change button state


Right now, we can only know if we have successfully follow a profile through the console log, so we need to change the text for the follow button, as well as set the initial state for every user. What we want to do is set the initial state as 'detached' with button text 'Follow' and change the text to 'Unfollow' once the it is 'attached'.

1) How do we determine if a user is following a profile? This is what this code does.

11
12
13
14
15
16
    public function index(User $user)
    {
        $follows =  (auth()->user()) ? auth()->user()->following->contains($user->id) : false;

        return view('profiles/index', compact('user', 'follows'));
    }
app > Http > Controllers > ProfilesController.php


Translation: If a user is authenticated ( auth()->user()) ), then ( ? ) grab the authenticated user's following ( auth()->user()->following-> ) contains the user ( contains($user->id) ) that are passed in (User $user). Otherwise ( : ), just return false (not following).

2) Pass the status to the view and change the state of the button

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<template>
    <div>
        <button class="btn btn-primary btn btn-primary btn-sm pl-4 pr-4 ml-3" style="font-weight:500"
            @click="followUser" v-text="buttonText"></button>
    </div>
</template>

<script>
import axios from 'axios'

export default {
    props: ['userId', 'follows'],

    mounted() {
        console.log('Component mounted.')
    },

    data: function () {
        return {
            status: this.follows,
        }
    },

    methods: {
        followUser() {
            axios.post('/follow/' + this.userId)
                .then(response => {
                    this.status = !this.status;

                    console.log(response.data);
                });
        }
    },

    computed: {
        buttonText() {
            return (this.status) ? 'Unfollow' : 'Follow';
        }
    }
}
</script>
resources > js > components > FollowButton.vue


3) Call the 'follow' status to the view


13
                    <follow-button user-id="{{ $user->id }}" follows="{{ $follows }}"></follow-button>
resources > views > profiles > index.blade.php

Redirect unauthorized user


When someone is logged out, they can still hit the follow button. But instead of letting the app send a 500 error to the console log, we should return a 401 (unauthorized) error and redirect them to the login page.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class FollowsController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
    }

    public function store(User $user)
    {
        //Attach and detach user's profile
        return auth()->user()->following()->toggle($user->profile);
    }
}
app > Http > Controllers > FollowsController.php


24
25
26
27
28
29
30
31
32
34
35
36
37
38
39
    methods: {
        followUser() {
            axios.post('/follow/' + this.userId)
                .then(response => {
                    this.status = !this.status;

                    console.log(response.data);
                })

                .catch(errors => {
                    if (errors.response.status == 401) {
                        window.location = '/login';
                    }
                });
        }
    },
resources > js > components > FollowButton.vue



That is all for this part. On the next part, we gonna learn how to count the following.





No comments:

Post a Comment