CommonLounge Archive

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:

  1. Insert a row in the follow table with appropriate values for sender and receiver.
  2. Increment the following count for sender and the follower count for receiver.

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 just user_id (without the :) refers to the user_id column in the users 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 to home.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_ids, 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");
}

© 2016-2022. All rights reserved.