Hands-on Project: Twitter Clone - Follow / Unfollow and Search
September 20, 2018
Welcome to the final part of this three part PHP Twitter Clone project! In this part, you will add the following features to the Twitter Clone: (a) follow or unfollow a user, (b) view the tweets of all the users that you follow and (c) use the search bar to search for a user. Let’s begin!
Step 1: Follow table
We have to create a table to store which user is following which user.
What columns should the table have? What attributes should each column have?
Create the follow
table using phpMyAdmin inside the twitter
database.
Solution to this section can be found in section Solution: Follow table below.
Step 2: Create some data
To add the follow / unfollow feature, we will need a few users on our site!
Create a new user by signing up and add a few tweets for that user. You can also change the default profile picture of the user from phpMyAdmin if you like. The new user profile should look something like this:
New user profile page
Step 3: Follow / Unfollow button
Okay, time to add the Follow / Unfollow button to your Twitter clone!
First, take a moment to think about when the button should be displayed. When should the follow / unfollow button not be displayed? When should it say follow? When should it say unfollow?
Answer:
If you are looking at your own profile (profileId
is equal to the user_id
), then no button should be displayed.
Else, if user user_id
doesn’t follow user profileId
, then display the Follow button. If the user_id
is already following the profileId
, display the Unfollow
button.
Open the project-resources
folder and copy the HTML from profile_2.html
and replace the HTML inside profile.php
(which you copied from profile_1.html
).
Add the following method displayBtn
to follow.php
.
public function displayBtn($user_id, $profileId) {
if ($user_id == $profileId) {
echo "";
} elseif ($this->checkFollow($user_id, $profileId) === true) {
// unfollow
echo '<span>You are following this user. </span>';
echo '<input type="submit" style="color: #FFFFFF; font-weight: bold; background-color: #d10000" name="unfollow" value="Unfollow"/>';
}
else {
// follow
echo '<input type="submit" style="color: #FFFFFF; font-weight: bold; background-color: #006eb7" name="follow" value="Follow"/>';
}
}
and then write your code for method checkFollow($user_id, $profileId)
.
Checkpoint: Login to your previous account and visit your own profile page. In this case, you should not see any follow / unfollow button:
No button is displayed if you look at your own profile
If you then visit the profile page of the user you just created through the URL, (in this case, you would type in http://localhost/twitter/profile.php?username=maxplanck
in the browser) you will see the Follow button:
Follow button is displayed when you visit some other user’s profile
Solution to this section can be found in section Solution: Follow / Unfollow button below.
Step 4: Follow method
Now, let’s implement the follow method. When the Follow
button is clicked, we want to do the following:
- Insert a row in the
follow
table with appropriate values forsender
andreceiver
. - Increment the
following
count forsender
and thefollower
count forreceiver
.
Implement this functionality as a method in the Follow
class, then call this method from profile.php
when the Follow
button is clicked.
Once you increment the counts, we also want the page to auto-refresh, so that the updated count is displayed. Use the function header("Refresh:0");
to do this.
Checkpoint: Now refresh the browser and click on the Follow button on the profile page of the new user:
When you follow a user, the Unfollow button is displayed and the followers count is incremented by one
Great! The Follow
button should change to Unfollow
and you should see a message “You are following this user”. The followers count for the user maxplanck
should increment by one as expected.
When you go to your own profile now, you should see that the following count is also incremented by one.
The following count is incremented by one
Finally, you can also check the entries in the follow
and users
table in phpMyAdmin:
New record inserted into the follow table
updated “following” and “followers” counts
Pretty straightforward, right?
Solution to this section can be found in section Solution: Follow method below.
Step 5: Update user feed
Now that we are able to follow one another, we need to display all the tweets of the users you follow in the user feed.
All you need to do is change the SQL query inside the tweets method (which you wrote inside the Tweet
class). Replace the line:
$stmt = $this->pdo->prepare("SELECT * FROM tweets, users WHERE (tweetBy = user_id AND user_id = :user_id) ORDER BY tweetId DESC");
with:
$stmt = $this->pdo->prepare("SELECT * FROM tweets, users WHERE (tweetBy = user_id AND user_id = :user_id) OR (tweetBy = user_id AND tweetBy IN(SELECT receiver FROM follow WHERE sender = :user_id)) ORDER BY tweetId DESC");
Note: In the query above,
:user_id
is the normal way we bind a variable. But justuser_id
(without the:
) refers to theuser_id
column in theusers
table. Keep this in mind if your column names are different.
Checkpoint: Go to your home page, and you should see all your tweets as well as the tweets of the user you are following:
After following a user, you will see all of his/her tweets in your feed
Amazing! The Follow
button works perfectly!
Step 6: Unfollow method
The Unfollow
method and logic is similar to the Follow
method, you just need to do the opposite. Delete a row instead of create, and decrement counts instead of increment.
Checkpoint: Click on the Unfollow
button, and check that the button changes to Follow
button. Also check that the follower
and following
count of profileId
and user_id
are decremented by one.
To go the feed and ensure that you no longer see the tweets of the user you unfollowed. Also verify the users
and follow
tables in phpMyAdmin are as expected.
Solution to this section can be found in section Solution: Unfollow method below.
Great! You successfully implemented the follow and unfollow feature in the project.
Play around with the follow / unfollow feature for a bit. Create new users and tweets and follow one another and see if everything you have done so far works as expected.
Step 7: Search feature
Time for the last feature of the project: searching users by username!
When a user types in a username in the search box on the top right corner, you have to redirect the user to http://localhost/twitter/profile.php?username=xxx
where xxx
is the username that the user typed in.
Search by username
For this, create a new method in the User
class:
public function searchByUsername($username) {
return BASE_URL.'profile.php?username='.$username;
}
Then, you need to check if the search button is pressed or not (in both home.php
and profile.php
). If pressed, call the searchByUsername()
method:
if (isset($_POST['search'])) {
$searchUserURL = $getFromU->searchByUsername($_POST['searchUsername']);
header('Location: '. $searchUserURL);
}
Simple, right?
Remember that if you type in a username that doesn’t exist, you will be redirected to
index.php
(and if we you are logged-in, you will be again redirected tohome.php
).
Summary
You finally made it! You completed creating the entire PHP Twitter Clone project — complete with all the basic features like sign-up / login, tweeting, user feed, user profile, follow / unfollow and search. Congratulations!
If you lost track, got stuck, or just need to double check, the solution for each of the above steps is included below. You can also find all the official implementation of the complete project here.
Where to go from here
This is a completely open ended project, and you can do as much more with it as you would like to. Here are some ideas:
- Allow users to edit the profile information like username, password, profile image, etc.
- Implement the like feature for the tweets. You will have to create a
likes
table for this. - Implement the retweet feature.
- Implement the reply feature. Again, you will need a new table to store which tweet is a reply to which tweet.
- Add some Javascript or JQuery to the project to make it more dynamic. One feature you can add using either of these is to mention a user inside a tweet using the @ sign.
- Another feature you can implement with JavaScript or JQuery is instant search for users. That is, you don’t need to type the full username. You start getting search results as soon as you start typing.
- Search tweets by hashtags (similar to above).
- Suggest who to follow
- Add images, GIFs and videos inside tweets.
- Set a account as private. This means only the users who follow you can see your tweets. The users will have to request to follow you and you have the option to accept or decline the request.
- If you want to take it to the next level, you can add a messaging system to chat with different users.
The possibilities are endless! You now have the skills to implement most of the features mentioned above. All you have to do is implement 🙂
Solution: Follow table
The table has 3 columns:
follow table
The sender
is the user who clicks the Follow
button to follow another user (the receiver
). We store their user_id
s, and hence the type is INT
.
Solution: Follow / Unfollow button
follow.php
:
<!-- follow.php -->
<?php
class Follow extends Base {
function __construct($pdo) {
$this->pdo = $pdo;
}
}
public function checkFollow($user_id, $profileId) {
$stmt = $this->pdo->prepare("SELECT * FROM follow WHERE sender = :user_id AND reciever = :profileId");
$stmt->bindParam(":user_id", $user_id, PDO::PARAM_INT);
$stmt->bindParam(":profileId", $profileId, PDO::PARAM_INT);
$stmt->execute();
$count = $stmt->rowCount();
if ($count > 0) {
return true;
} else {
return false;
}
}
public function displayBtn($user_id, $profileId) {
if ($user_id == $profileId) {
echo "";
} elseif ($this->checkFollow($user_id, $profileId) === true) {
// unfollow
echo '<span>You are following this user. </span>';
echo '<input type="submit" style="color: #FFFFFF; font-weight: bold; background-color: #d10000" name="unfollow" value="Unfollow"/>';
}
else {
// follow
echo '<input type="submit" style="color: #FFFFFF; font-weight: bold; background-color: #006eb7" name="follow" value="Follow"/>';
}
}
?>
Solution: Follow method
Follow
class methods:
public function follow($user_id, $profileId) {
$this->create('follow', array('sender' => $user_id, 'receiver' => $profileId));
$this->addFollowCount($user_id, $profileId);
}
public function addFollowCount($user_id, $profileId) {
$stmt = $this->pdo->prepare("UPDATE users SET following = following + 1 WHERE user_id = :user_id;UPDATE users SET followers = followers + 1 WHERE user_id = :profileId;");
$stmt->bindParam(":user_id", $user_id, PDO::PARAM_INT);
$stmt->bindParam(":profileId", $profileId, PDO::PARAM_INT);
$stmt->execute();
}
profile.php
- call the follow()
method when the Follow
button is clicked (and refresh the page):
if (isset($_POST['follow'])) {
$getFromF->follow($user_id, $profileId);
header("Refresh:0"); // Refresh the page
}
Solution: Unfollow method
Follow
class methods:
public function unfollow($user_id, $profileId) {
$this->delete('follow', array('sender' => $user_id, 'receiver' => $profileId));
$this->removeFollowCount($user_id, $profileId);
}
public function removeFollowCount($user_id, $profileId) {
$stmt = $this->pdo->prepare("UPDATE users SET following = following - 1 WHERE user_id = :user_id;UPDATE users SET followers = followers -1 WHERE user_id = :profileId;");
$stmt->bindParam(":user_id", $user_id, PDO::PARAM_INT);
$stmt->bindParam(":profileId", $profileId, PDO::PARAM_INT);
$stmt->execute();
}
profile.php
- call the unfollow()
method when the Unfollow
button is clicked (and refresh the page):
if (isset($_POST['unfollow'])) {
$getFromF->unfollow($user_id, $profileId);
header("Refresh:0");
}