Custom implementation for Wall, Messages and Like Button

The ubiquitous “Like” button…it’s nice, easy to use and pretty damn useful.
If you ever wondered how can you implement it on your website..well, it’s very easy and it’s called Facebook Like Button: http://developers.facebook.com/docs/reference/plugins/like/, but that’s not what I want to talk about here.
Now, imagine the next situation: you have a simple web application in which each user can have a Wall and can post on each other’s or on its own wall. What? Facebook has this functionality too :) ?
Currently being my first language of choice, I will explain the implementation in PHP / MySQL. First of all, you should have a simple database structure, like the one below:

Just to be sure you understood the structure:
- a user (wall_entries.user_id) can post a message (wall_entries.message) on other’s or on it’s own (wall_entries.to_user_id) wall;
- the message (wall_entries_likes.wall_entry_id) can be liked/unliked by others or by the author (wall_entries_likes.user.id);
- the message can have one or more replies (wall_entries_messages.message) from others or from the author (wall_entries_messages.user_id);
- the replies (wall_entries_messages_likes.wall_entry_id) can be liked/unliked by others or by the author (wall_entries_messages_likes.user_id)
Let’s take a look at the SELECT statement which retrieve all the messages and likes that belongs to the first user Wall:

SELECT
`wall_entries`.`id`,
`wall_entries`.`user_id`,
`users`.`name` AS `user_name`,
`wall_entries`.`to_user_id`,
`u2`.`name` AS `to_user_name`,
`wall_entries`.`message`,
(
SELECT
GROUP_CONCAT(user_id)
FROM
wall_entries_likes
WHERE
wall_entry_id = wall_entries.id
GROUP BY
wall_entry_id
)AS `user_ids_liked`,
(
SELECT
GROUP_CONCAT(users. NAME)
FROM
wall_entries_likes
INNER JOIN users ON users.id = wall_entries_likes.user_id
WHERE
wall_entry_id = wall_entries.id
GROUP BY
wall_entry_id
)AS `user_names_liked`
FROM
`wall_entries`
LEFT JOIN `users` ON users.id = wall_entries.user_id
LEFT JOIN `users` AS `u2` ON u2.id = wall_entries.to_user_id
WHERE
(to_user_id = '1')


Now, let’s take a look at the SELECT statement which retrieve all the replies and likes of all the messages that belongs to the first user Wall:

SELECT
`wall_entries_messages`.`id`,
`wall_entries_messages`.`wall_entry_id`,
`wall_entries_messages`.`user_id`,
`users`.`name` AS `user_name`,
`wall_entries`.`to_user_id`,
`u2`.`name` AS `to_user_name`,
`wall_entries_messages`.`message`,
(
SELECT
GROUP_CONCAT(user_id)
FROM
wall_entries_messages_likes
WHERE
wall_entry_id = wall_entries_messages.id
GROUP BY
wall_entry_id
)AS `user_ids_liked`,
(
SELECT
GROUP_CONCAT(users. NAME)
FROM
wall_entries_messages_likes
INNER JOIN users ON users.id = wall_entries_messages_likes.user_id
WHERE
wall_entry_id = wall_entries_messages.id
GROUP BY
wall_entry_id
)AS `user_names_liked`
FROM
`wall_entries_messages`
INNER JOIN `wall_entries` ON wall_entries.id = wall_entries_messages.wall_entry_id
LEFT JOIN `users` ON users.id = wall_entries_messages.user_id
LEFT JOIN `users` AS `u2` ON u2.id = wall_entries.to_user_id
WHERE
(wall_entries.to_user_id = 1)


So far, you can clearly see that Tom Cat who posted on John Doe’s Wall got 2 replies from Indiana Jones and John Doe and only the reply from Indiana Jones was liked by two people: John Doe and Tom Cat! Whoaa!
Let’s take a look at the View Helper which generates the HTML near the Like button:

/**
* Generate the HTML that will be displayed near the Like button
*
* @return string
*/
public function wallEntryLikes($item, $userId)
{
$isLikedByCurrentUser = false;
$wallEntryLikesHtml = '';
 
//Check if the wall entry is liked by current user
if(XX_Utilities_Like::getInstance()->isLikedByCurrentUser(
$item, $userId)
){
$wallEntryLikesHtml .= 'You';
$isLikedByCurrentUser = true;
}
 
$userIds = '';
 
//Check if other users like the current wall entry
if($item->user_ids_liked){
$userIds = explode(',', $item->user_ids_liked);
$userNames = explode(',', $item->user_names_liked);
 
//The wall entry is liked by the current user and one or multiple users
if($isLikedByCurrentUser){
if(count($userIds) - 1 == 0){
$wallEntryLikesHtml .= ' like this';
}
else if(count($userIds) - 1 == 1){
$wallEntryLikesHtml .= ' and '
. $userNames[array_search($userId, $userIds)]  . ' like this';
}
else {
$wallEntryLikesHtml .= ' and ' . (count($userIds) - 1) . ' others like this';
}
}
//The wall entry is liked by one or multiple users
else{
if(count($userIds) == 1){
$wallEntryLikesHtml .= $userNames[0] . ' like this';
}
else if(count($userIds) == 2){
$wallEntryLikesHtml .= $userNames[0] . ' and '
. $userNames[1] . ' like this';
}
else{
$wallEntryLikesHtml .= $userNames[0] . ' and '
. (count($userIds) - 1) . ' others like this';
}
}
}
 
if ($wallEntryLikesHtml){
return '' . $wallEntryLikesHtml . '';
}
 
return '';
}

Happy coding!

Comments are closed.