Social Network Style Posting with PHP, MongoDB and jQuery – part 2

Share this article

In the previous part of the series, we explained the database architecture, post stream design and application flow required for developing our post mechanism wherein the user will be able to post a status, like/unlike other people’s statuses and comment on them. This part of the series will drive you through the coding required to implement these functionalities. We will use the application flow and database structure as discussed in the last article. Don’t forget to download the code from the github repo if you’d like to follow along.

Insert Post:

In our index.php file, we had added a Create New Post button. Clicking it will call a JavaScript function new_post with the user id from the session as its parameter.

<input type="button" value="Create New Post" id="btn_new_post" 
onClick="new_post('<?php echo $_SESSION['user_id']; ?>')" class="button_style"/>

Referring to the code in script.js, let us understand the function new_post step-by-step:

We first get the post text in a variable new_post_text and check if this text is empty using JavaScript’s trim function. If the text is empty, we show an alert message to enter the post text.

function new_post(user_session_id) 
{    
    var new_post_text = $('#post_textarea').val();
    if(!$.trim(new_post_text))
    {
        alert("Please enter some text in the post");
           return;    
    }

We then send an AJAX POST request using jQuery’s $.POST function:

$.post('php_scripts/insert_new_post.php',{
     user_id: user_session_id,
post_text: new_post_text
},function(output){
         // code to be executed after success of AJAX call
    });

The format of jQuery’s $.POST function is:

jQuery.post(url,{parameter:value}, success(output){ //function body });

The first parameter is the url of the file to be called. The second parameter is list of parameters to be sent to the url. The third parameter is a callback function that is executed if the AJAX request succeeds. The variable output contains the output received from the called file.

So, in our case we are calling insert_new_post.php, while passing user id and post text as parameters. We will get back to this function later to write the code inside the callback function.

Next, open the file insert_new_post.php in the php_scripts folder. This is the file wherein we will write the code that interacts with the database. First of all, we create a new post id using new MongoId(). We then get the user id and post text passed from the JS function using the $_POST superglobal. As you might know, a MongoID is a combination of time and other parameters. We fetch the creation time of the post using post_id and the getTimestamp function. We will be using this timestamp as the creation time of our post.

$post_id = new MongoId();
$user_id = new MongoId($_POST['user_id']);
$user_session_id = new MongoId($_SESSION['user_id']);
$post_text = $_POST['post_text'];
$timestamp=date('D, d-M-Y', $post_id->getTimestamp());

Then, we check if the user id received through the AJAX request is same as the current session’s user id. This is just a small check to confirm that the file is called from the correct source – we don’t want a user performing the actions for someone else. We then create a document containing all the post elements and execute an insert function with the same.

if($user_id == $user_session_id)
{
    $collection = $database->selectCollection('posts_collection');
    $new_post_mongo = array ( '_id'=> $post_id,
                              'post_author_id' => $_SESSION['user_id'],
                              'post_text' => $post_text,
                              'total_likes' => 0,
                              'likes_user_ids' => array (),
                              'comments' => array (),
                              'total_comments' => 0,
                              'timestamp'=>$timestamp
                            );
    $collection->insert($new_post_mongo);                          
}

Once the new document is inserted into the database, we have to show the newly inserted post on our index page. For this we will create and send HTML content from here, and this output will be received as output by the jQuery function new_post which called this page. The code to generate this HTML is similar to what we did to display each post on the home stream in the previous article. So, I am skipping this part of explaining the same code again here. You can refer to the code after query insertion in insert_new_post.php.

Going back to the jQuery function new_post, let us modify the post success logic inside the callback. Here, we prepend the output received to the existing post stream using the prepend method and then display it using jQuery hide and slideDown animation. Lastly, we clear all the existing content of the post textarea.

$.post(insert_new_post_filename,{
    user_id: user_session_id,
    post_text: new_post_text},function(output){
               $('#post_stream').prepend(output);
    var new_post_id=$("#post_stream div:first-child").attr("id");
    $("#"+new_post_id).hide().slideDown();
    $('#post_textarea').val(null);
});

That’s all. We are done with the whole process of inserting a new post and displaying it back on our index page without refreshing the whole page. Let us now quickly see a similar process for liking/unliking the posts.

Like/Unlike Posts:

Locate the span for displaying the Like/Unlike label in index.php. Add an onclick function call post_like_unlike with the current session user id as its parameter.

<span class="post_feedback_like_unlike" id="<?php echo $post_like_unlike_id;?>"  
onclick="post_like_unlike(this,'<?php echo $_SESSION['user_id']; ?>')">
    <?php echo $like_or_unlike; ?>
</span>

In this JS function, we will first check whether the user has clicked Like or Unlike. For this, we grab the HTML text (Like/Unlike) of the span element declared above using the id property of post_id_like_unlike received as the parameter. Here, type will contain the text Like or Unlike.

function post_like_unlike(post_id_like_unlike,user_session_id)
{
    var type = ($('#'+(post_id_like_unlike.id)).html());
    ..

We also get the post id as the first part after splitting the span id. Remember that we had declared span id in the previous article like this:

$post_like_unlike_id=$post_id.'_like_unlike';

The reason for declaring elements like this must be clear to you now. This allows us to use the post id in the JS as we are doing now:

var post_id_of_like_unlike= ((post_id_like_unlike.id).split("_")) [0];
var post_id_like_count = post_id_of_like_unlike+'_like_count';

If the user has clicked on Like we send an AJAX call to post_like.php. Else, we call post_unlike.php. In the callback function, we change the text of Like/Unlike option to Unlike if the user has clicked on Like and vice versa. Also, we increase/decrease the likes count using post_id_like_count.

if (type == 'Like')
{
   $.post('php_scripts/post_like.php',{
        post_id:post_id_of_like_unlike,
        user_id:user_session_id},function(output){
            $('#'+(post_id_like_unlike.id)).html('Unlike');
            $('#'+(post_id_like_count)).html(parseInt($('#'+(post_id_like_count)).html())+1);
       });
}
else 
{
    $.post('php_scripts/post_unlike.php',{
        post_id:post_id_of_like_unlike,
        user_id:user_session_id},function(output){
            $('#'+(post_id_like_unlike.id)).html('Like');
            $('#'+(post_id_like_count)).html(parseInt($('#'+(post_id_like_count)).html())-1);
        });
};

In post_like.php, we update the post document by incrementing total_likes by 1 and pushing the current user id in the array likes_user_ids.

$collection->update(array('_id' =>$post_id),
                    array('$push' => array('likes_user_ids'=>$user_id),
                          '$inc' => array('total_likes' => 1 )) 
                    );

Similarly, in post_unlike.php, we update the post document by decrementing total_likes by 1 and pulling the user id from the array likes_user_ids.

$collection->update(array('_id' => $post_id),
                    array('$pull' => array('likes_user_ids'=>$user_id),
                          '$inc' => array('total_likes' => -1 )) 
                    );

Inserting Comments:

After understanding how the post insertion and like/unlike functionalities work, you will be able to easily understand how the commenting functionality works. After passing the comment text and post id from index.php to JS and then to new_comment.php, we will update the post document to insert the new comment and increment the count.

$collection->update(array('_id' => $post_id),
                    array('$push' => array('comments'=> array (
                                                'comment_id'=>$comment_id,
                                                'comment_user_id' =>$user_id,
                                                'comment_text' => $comment_text
                                               )),      
                           '$inc' => array('total_comments' => 1 ))
                    );

We will then append this new comment to the existing list of comments on the post.

Finally, we have implemented everything we’ve set out to implement. Fig 1 shows what our final working application looks like. (Note that in the figure, you can see three users. For the purpose of this demonstration, I have changed these users from the session_variables.php file.)

Conclusion:

In the two articles of this series, we learned how to design the database schema, understood the HTML structure, and then implemented the whole post mechanism. However, note that the article only shows one way of achieving these features, which may not be the same approach such social networks use. Also, there are lots of other features and issues (security, design, etc.) to be considered in such applications that we may not have discussed here.

Furthermore, the code does not follow best practices – this is something for the reader to experiment with. Implement object oriented code, use a JavaScript framework, use a PHP framework for the entire back end – the sky is the limit. This post mechanism is merely a hint of how you can implement a single feature in your own social network.

To conclude, this article is just a foundation of many things you can achieve using similar concepts. You can go ahead and implement a lot of features which I could not explain here like displaying names of users who liked the post, showing collapsible comments, deleting comments, deleting posts, liking/unliking comments, popular posts, building a more interactive post stream showing posts from user’s friends and other advanced features. If you have any suggestions or critiques, please leave them in the comments below.

Frequently Asked Questions (FAQs) about Social Network Style Posting with PHP, MongoDB, and jQuery

How can I ensure data security when using MongoDB with PHP and jQuery?

Data security is a critical aspect when working with databases like MongoDB. To ensure data security, you can use MongoDB’s built-in security features such as authentication, authorization, and auditing. Additionally, always validate and sanitize user inputs to prevent injection attacks. Use PHP’s filter_var() function to sanitize user inputs and jQuery’s $.ajax() method to send asynchronous requests securely.

Can I use other databases instead of MongoDB for social network style posting?

Yes, you can use other databases like MySQL, PostgreSQL, or SQLite for social network style posting. However, MongoDB offers advantages such as scalability, flexibility, and performance which make it suitable for handling large amounts of data typical in social networks.

How can I optimize the performance of my MongoDB database?

To optimize MongoDB performance, use indexing to speed up query performance. Regularly monitor your database performance using MongoDB’s database profiler and optimize your queries accordingly. Also, consider sharding your data across multiple servers for improved performance and scalability.

How can I handle errors when using PHP, MongoDB, and jQuery?

Error handling is crucial for building robust applications. In PHP, you can use try-catch blocks to handle exceptions. In MongoDB, use the write concern feature to handle errors during data operations. In jQuery, use the error callback function in the $.ajax() method to handle errors during AJAX requests.

How can I implement real-time updates in my social network style posting application?

To implement real-time updates, you can use technologies like WebSockets or Server-Sent Events (SSE). These technologies allow the server to push updates to the client in real-time. You can also use AJAX polling, where the client regularly sends requests to the server to check for updates.

How can I paginate results in MongoDB?

To paginate results in MongoDB, you can use the limit() and skip() methods. The limit() method specifies the maximum number of results to return, while the skip() method specifies the number of documents to skip.

How can I implement search functionality in my application?

To implement search functionality, you can use MongoDB’s text search feature. Create a text index on the fields you want to search and use the $text operator to perform text searches. You can also use regular expressions for more complex search patterns.

How can I handle file uploads in my application?

To handle file uploads, you can use the HTML5 File API along with jQuery’s AJAX capabilities. On the server-side, use PHP’s $_FILES array to access uploaded files. You can also use MongoDB’s GridFS feature to store and retrieve large files such as images or videos.

How can I ensure my application is responsive and user-friendly?

To ensure your application is responsive and user-friendly, use jQuery’s AJAX capabilities to update parts of the web page without reloading the entire page. Use CSS and JavaScript to create a responsive and interactive user interface. Also, ensure your application is accessible by following the Web Content Accessibility Guidelines (WCAG).

How can I scale my application to handle more users?

To scale your application, you can use MongoDB’s sharding feature to distribute your data across multiple servers. Use load balancing to distribute network traffic across multiple servers. Also, optimize your application’s performance by using efficient queries, indexing, and caching.

Ashish TrivediAshish Trivedi
View Author

Ashish is a Computer Science Engineer and works for one of the Big Four firms as a Technology Analyst. Prior to this, he co-founded an educational start-up. In his free time, Ashish read and write blogs, watches animation cartoons, movies or discovery channel. You can find his recent blogs on http://ashishtrivediblog.wordpress.com/

ajaxjQuerymongoPHPsocial network
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week