Selecting individual notifications and preparing a clearer notification

I created a notification system, and that is pretty good. There are a few things you need to work on to make them perfect - so here I am.

The application I'm working on is a website written in PHP.

My notifications have a seen column that indicates whether a notification was detected or not. This column is updated when the user clicks the notification drop-down button, which is very similar to Facebook.

There are several cases where there are two identical notifications - the same user with the same address (URL). I want the notifications to be selected in a unique way, and the ones that need to be ignored. I don’t even understand how these identical are stored in the first place.

In any case, an approximate array of notifications is presented here:

 Array ( [0] => Array ( [notification_id] => 34 [receiver_id] => 9 [notification_issuer] => 11 [notification_message] => Dugipo has liked your image [notification_target] => http://localhost/imgzer/image/v2M6S2V1J3h7 [notification_type] => like [notification_time] => 1391291043 [notification_seen] => 1 [user_avatar] => [username] => Dugipo ) [1] => Array ( [notification_id] => 33 [receiver_id] => 9 [notification_issuer] => 11 [notification_message] => Dugipo has liked your image [notification_target] => http://localhost/imgzer/image/v2M6S2V1J3h7 [notification_type] => like [notification_time] => 1391288815 [notification_seen] => 1 [user_avatar] => [username] => Dugipo ) [2] => Array ( [notification_id] => 32 [receiver_id] => 9 [notification_issuer] => 11 [notification_message] => Dugipo has liked your comment [notification_target] => http://localhost/imgzer/image/o3F6g8b8t6Q0#cid-64 [notification_type] => like [notification_time] => 1391216243 [notification_seen] => 1 [user_avatar] => [username] => Dugipo ) [3] => Array ( [notification_id] => 31 [receiver_id] => 9 [notification_issuer] => 11 [notification_message] => Dugipo has liked your image [notification_target] => http://localhost/imgzer/image/o3F6g8b8t6Q0 [notification_type] => like [notification_time] => 1391216135 [notification_seen] => 1 [user_avatar] => [username] => Dugipo ) [4] => Array ( [notification_id] => 30 [receiver_id] => 9 [notification_issuer] => 11 [notification_message] => Dugipo has liked your image [notification_target] => http://localhost/imgzer/image/o3F6g8b8t6Q0 [notification_type] => like [notification_time] => 1391214642 [notification_seen] => 1 [user_avatar] => [username] => Dugipo ) ) 

As you can see, there are two pairs of identical arrays, and this is not what I need. I also try to achieve an effect when two or more people like the same thing, messages become like this: X, Y and n others like your image

I can’t think about how I will do it. In any case, this is a function / method that collects notifications:

 public function getNotifications($seen = false) { global $db; $seen = ($seen === true) ? 1 : 0; $limit = ($seen === true) ? 5 : 10; $sql = 'SELECT n.*, u.user_avatar, u.username FROM ' . NOTIFICATIONS_TABLE . ' n LEFT JOIN ' . USERS_TABLE . " u ON n.notification_issuer = u.user_id WHERE receiver_id = ? AND notification_seen = $seen ORDER BY notification_time DESC LIMIT 5"; $query = $db->prepare($sql); $query->execute(array($this->id)); $result = $query->fetchAll(PDO::FETCH_ASSOC); /*for ($i = 0; $i < sizeof($result); $i++) { if ($result[$i]['notification_message'] == $result[++$i]['notification_message']) { $new_message = ''; if ($result[$i]['notification_issuer'] != $result[++$i]['notification_issuer']) { $new_message .= ''; } } }*/ return $result; } 

The commented-on for loop was supposed to create the effect when people who loved a certain thing became the only notification, and the names were separated by a comma and "and" for other people who liked the image.

This is the function / method in which notifications are stored:

 public function sendNotification($notification, $receiver, $notification_target = null, $notification_type = 'default') { global $db; $sql = 'INSERT INTO ' . NOTIFICATIONS_TABLE . '(receiver_id, notification_issuer, notification_message, notification_target, notification_type, notification_time) VALUES (?, ?, ?, ?, ?, ?)'; $query = $db->prepare($sql); $query->execute(array($receiver, $this->id, $notification, $notification_target, $notification_type, time())); } 

An example of using this method:

 // Send notification / Make sure that the notification sender isn't the same user that going to receive the notification if ($user->get_data('user_id') != $this->image_uploader_id) { $user->sendNotification( sprintf('<strong>%s</strong> has liked your image', $user->get_data('username')), $this->image_uploader_id, self::convert('name2url', $this->image_name), 'like' ); } 

Finally, here is the notification table schema:

 +----------------------+---------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +----------------------+---------------------+------+-----+---------+----------------+ | notification_id | int(11) unsigned | NO | PRI | NULL | auto_increment | | receiver_id | int(11) unsigned | NO | | NULL | | | notification_issuer | int(11) unsigned | NO | | NULL | | | notification_message | varchar(255) | NO | | NULL | | | notification_target | varchar(255) | YES | | NULL | | | notification_type | varchar(55) | NO | | default | | | notification_time | int(11) unsigned | NO | | NULL | | | notification_seen | tinyint(1) unsigned | NO | | 0 | | +----------------------+---------------------+------+-----+---------+----------------+ 

SQL Fiddle: http://www.sqlfiddle.com/#!2/6970b/1


So, I basically after two things:

  • Be able to select unique lines. Duplicate lines are ignored
  • Achieve the effect to combine notifications that have the same goal into one notification, which then shows the names of individuals of the same action (for example, like) as follows: X, Y, Z and others liked your image.

So, after SELECT from the database, I would like all users who created a notification for the same target to become a beautifully readable string, as I described above. I try to avoid users who loved / did not like / commented on the same goal in order to have a separate notification to the recipient - they must be concatenated somehow.

So, let's say the action is like an image. The five users of image_like-d are the same notification_target , or now we can determine what the user will be notified about with notification_type (which will be image_like) and reference_id (we will know that this will be the image now); So now we have a complete idea of ​​what image_id is based on reference_id , and we also know this image because notification_type says the image is _like.

So, with this table:

 id reference target issuer_id type 1 25 tg1 43 like 2 25 tg1 23 like 3 53 tg2 77 comment 4 53 tg2 23 comment 5 53 tg2 67 comment 6 53 tg2 98 dislike 7 34 tg3 65 like 

From this table, these will be the following results:

  • User43 and User23 liked reference25 (links to tg1)
  • User77, User23 and User67 commented on link 53 (links to tg2)
  • User 98 does not like link53 (links to tg2)
  • User65 liked reference34 (links to tg3)

Any help would be appreciated.

+6
source share
2 answers

I use only the part of the request that solves your first and second requirements, assuming that your data remains in one structure. You can add connections and other necessary data to your request.

SELECT myView.*, CONCAT(REPLACE(REPLACE(group_concat(SUBSTRING(notification_message,9)),'</strong>',''),SUBSTRING_INDEX(notification_message,'>',-1),''), SUBSTRING_INDEX(notification_message,'>',-1)) AS Message
FROM (SELECT DISTINCT receiver_id, notification_issuer, notification_message, notification_target, notification_type FROM imgzer_notifications
WHERE receiver_id = 9 and notification_seen = 1 ORDER BY notification_time DESC) myView GROUP BY myView.receiver_id, myView.notification_target, myView.notification_type;

I know that String functions look complicated, but in order to achieve the desired result, I had to play with strings. I slightly modified my dataset in SQL Fiddle to check my output. You can do the same:

http://www.sqlfiddle.com/#!2/70a937/49

Let me know if there are any other criteria that must be met, or any extension that you require in the request.

+4
source

Having made a lot of assumptions about your data, something like this: -

 public function getNotifications($seen = false) { global $db; $new_message = ''; $seen = ($seen === true) ? 1 : 0; $limit = ($seen === true) ? 5 : 10; $sql = 'SELECT n.receiver_id, n.notification_type, GROUP_CONCAT(DISTINCT CONCAT_WS(':', u.username, u.user_avatar)) AS msgs, MAX(n.notification_time) AS LatestTime FROM ' . NOTIFICATIONS_TABLE . ' n LEFT OUTER JOIN' . USERS_TABLE . " u ON n.notification_issuer = u.user_id WHERE receiver_id = ? AND notification_seen = $seen GROUP BY n.receiver_id, n.notification_type ORDER BY LatestTime DESC LIMIT $limit"; $query = $db->prepare($sql); $query->execute(array($this->id)); while ($row = $query->fetch(PDO::FETCH_NUM, PDO::FETCH_ORI_NEXT)) { $notif = explode(',', $row['msgs']); switch (count($notif)) { case 0 : // Should never happen break; case 1 : $aNotif = explode(":", $notif[0]); $new_message .= "<img='".$aNotif[1]."' />".$aNotif[0]." has ".$row['notification_type']." your event."; break; default : foreach($notif AS $key=>$oneNotif) { $aNotif = explode(":", $oneNotif); switch ($key) { case 0: $new_message .= "<img='".$aNotif[1]."' />".$aNotif[0]; break; case (count($notif) - 1): $new_message .= " and <img='".$aNotif[1]."' />".$aNotif[0]; break; default: $new_message .= ", <img='".$aNotif[1]."' />".$aNotif[0]; break; } } $new_message .= " has ".$row['notification_type']." your event by ".$row['LatestTime']."."; break; } } return $new_message; } 

The problem is that the notification time is not used (I don’t know where I will use the latter), I’m not sure what you want to do with the images (I guessed, but probably wrong), and a few other low bits.

EDIT

SQL for what I think you want now.

This gives you all the notifications (for the recipient it is visible or not visible), for the last 5 links there is a notification.

 SELECT n.reference_id, GROUP_CONCAT(n.notification_message) AS msgs FROM ' . NOTIFICATIONS_TABLE . ' n INNER JOIN ( SELECT receiver_id, notification_seen, reference_id, notification_issuer, MAX(notification_time) as max_notification_time FROM ' . NOTIFICATIONS_TABLE . ' WHERE receiver_id = ? AND notification_seen = ? GROUP BY receiver_id, notification_seen, reference_id, notification_issuer ) Sub1 ON n.receiver_id = Sub1.receiver_id AND nnotification_seen = Sub1.notification_seen AND n.reference_id = Sub1.reference_id AND n.notification_issuer = Sub1.notification_issuer AND n.notification_time = Sub1.max_notification_time GROUP BY n.reference_id ORDER BY reference_id, notification_time DESC LIMIT $limit 

EDIT again

Using your latest updated data, this SQL will do this: -

 SELECT n.receiver_id, n.reference_id, n.notification_type, CONCAT_WS(' ', GROUP_CONCAT(u.user_name), n.notification_type, n.reference_id) AS msgs, MAX(max_notification_id) as max_max_notification_id FROM imgzer_notifications n INNER JOIN ( SELECT receiver_id, reference_id, notification_issuer, notification_type, MAX(notification_id) as max_notification_id FROM imgzer_notifications WHERE receiver_id = ? AND notification_seen = ? GROUP BY receiver_id, reference_id, notification_issuer, notification_type ) Sub1 ON n.receiver_id = Sub1.receiver_id AND n.reference_id = Sub1.reference_id AND n.notification_issuer = Sub1.notification_issuer AND n.notification_id = Sub1.max_notification_id AND n.notification_type = Sub1.notification_type INNER JOIN imgzer_users u ON n.notification_issuer = u.user_id GROUP BY receiver_id, n.reference_id, n.notification_type ORDER BY max_max_notification_id DESC LIMIT $limit 

The message is a mess though (the last comma between the notification publishers is not replaced by and, and it should change “like” to “liked”, etc.).

What this means is the receipt of the latest notification for each issuer of notifications for each link. Then it joins the notifications to get the rest of the information, and uses GROUP_CONCAT to combine them into one line for a specific link and type of notification. CONCAT_WS is used to add a notification type and any constant text, and it is ordered by the highest maximum notification identifier omitted from the subquery. Thus, these are the types of links / notifications that contain the last notification that is indicated first (even if some of the notifications in this message are not the last). A.

The SQL script for this setting is here: -

http://www.sqlfiddle.com/#!2/4d876/1

+3
source

All Articles