How To Count Read and Unread message in PHP mysql - php

I want to make a read and Unread message count from Mysql.
This is my PHP code :
<?php
$dbdata = "SELECT * FROM users";
if ($result = mysqli_query($db, $dbdata)) {
if (mysqli_num_rows($result) > 0) {
while ($row = mysqli_fetch_array($result)) {
echo "<li class=online'><a href='?user=" .
$row['username'] .
"'><img alt='user pics' src='img/demo/av1.jpg' /> <span>" .
$row['fname'] . ' ' .
$row['lname'] . "</span><span class='msgcount'> 0</span></a></li>";
}
mysqli_free_result($result);
} else {
echo "No Students Found.";
}
} else {
echo "ERROR: Could not able to execute. ";
}
?>
I want <span class='msgcount'> 0</span> to display a count of the unread messages of that user. And if the user is already clicked, the messages unread becomes 0 because messages are shown upon click.
Can you help me solve this logic? I just want to notify that there is an unread message. Thank you masters please help me.
This is the Output image of the Chat Message:

I am new to php. So this can serve as an alternative till a better answer is tendered.
You could create a table that looks like that of your message. Then when you send a message insert the data into the two tables. Next, select your message in your normal way. And select the number of rows from your look alike table then print it in the span for unread messages. Then onclick let mysqli delete the messages from the look alike table. Autoupdate the span with jquery.

I'm assume that besided the users table, you alse have a messages table.
And I will boldly assume your messages table looks like this:
id int pk,
to_user_id int fk,
from_user_id int fk,
read bool default false,
title varcher(250),
body text,
created_at datetime,
updated_at datetime
So, users and messages have a 1:M relationship and rightfully so
You join, filter and count users and messages at every page load or at every few seconds
SELECT u.id, u.name as from, count(1) as total
FROM users AS u
JOIN messages AS m on u.id = m.from_user_id
WHERE
to_user_id = ? -- this is the authenticated user id!
AND `read` is false
GROUP BY from_user_id
This will give you tuples like so:
id, from, total
22, john, 1
124, frank, 3
523, bob, 1
11, david, 3
But this will require some more work, because this will only return the users with unread messages. So you can easily check if there are any messages by friends.
If you want just a general message count to show, for example on a banner:
SELECT count(1) FROM messages WHERE `read` is false and to_user_id = ? -- ? is the authenticated user id
Extra:
There are tons of fancier ways to go, like using redis to cache the message count.
What I've just describe is probably the simpler and uses zero auxiliar infrastructure, aka the burn mysql burn strategy.
pro tip:
if your application is going to rely heavily on messages like a slack type of app, it's not a good idea to store messages in a SQL database. But if you are just learning or tinkering, go ahead!

In your database create a column "Status" of datatype int(1) Default 0.
If I read the message update the status with 1, as by default we are using 0 that means its unread message.
Now at the time counting. Create two variables $total_read = 0 and $total_unread = 0.
Inside your while loop your can go with this
while($row = mysqli_fetch_array($result)) {
if($row['status'] == 0)
{
$total_unread = total_unread + 1
} else {
$total_read = total_read + 1
}
}

Related

Generating information based on users choice in php

I have any information stored in a database which is picked up and displayed with radio buttons. I like to display information from the database based on what radio buttons the user has chosen. For example I have a list of activities a user may have done and based on what they have chosen I would like to display other activities they could do. I can get the system to display random information from the database using RAND(). Can't find any online tutorials for this.
Please give us more information or a concrete example of your problem, all i can tell you is that your SQL request in your second code snippet will probably not give the expected result :
SELECT * FROM activities ORDER BY RAND() LIMIT 1
You probably don't want to ORDER BY RAND() (may be impossible) nor LIMIT 1, you just want to pickup one random row from your mysql results, am i right ?
If i am right just get the full resultset (with no order by / no limit clause), generate a random with php (between 0 and resultset size) the pick the expected row from resultset.
Ok, so i don't know your database structure, but lets say you have a table for activities and table for the activities the user does. For the sake of this example we will call them activities and activities_by_user
The activities table will have columns
activity_id | activity
The activities_by_user will have columns
activity_id | user_id
So your display code will look something like this
$query = "SELECT activities.*, activities_by_user.activity_id AS has_activity FROM activities LEFT JOIN activities_by_user ON activities_by_user.activity_id = activities.activity_id AND user_id = 1 ORDER BY RAND()";
// The user_id in just for example. There should be the id of the logged user
$result = mysqli_query($con, $query) or die('Error');
while($row = mysqli_fetch_object($result)) {
// If the has_activity field is not null, then the user does that activity
$checked = (isset($row->has_activity) && $row->has_activity != null) ? 'checked' : '';
echo '<label><input type="checkbox" name="activities[]" value="' . $row->activity_id . '" ' . $checked . ' />' . $row->activity . '</label>';
}
This will generate checkboxes for all the activities and will check does who are done by the user.

How to query SQL database from php on which user didn't send in his hour report for the last 30 days

I have an hoursheet import form where users submit the hours they worked per day. This data is send to a table called hours.
This table contains the columns:
user, day, hours, begintime, endtime
I want to send every employee an email when they didn't send in their worked hours per day.
What I've tried so far: create an array with the active users. I created an array from an sql query in php with all the hoursheets per user from 'yesterday'.
With array_diff_assoc I have the users which didn't send in their hoursheet for 'yesterday'.
So no problem here. But I'm looking for a more clean solution that can do it for several days in the past. Let's say the last month. Does anybody have a good suggestion to push me in the right direction?
Database is sql
Programming language php
Don't get me wrong, I don't need tons of code. I'm not lazy I want to try to look for this myself. I just need a push in the right direction.
Real-life example:
Table structure:
Hourimport table <----one to many <---- User table
|
one to many
|
Hourimport detail
Hourimport contains the dayreports unique record number, user, date, status, mail
Hourimport detail contains the details records of the dayreport. Multiple detail records per day.. For example one travel hour from 8 to 9 and working hours from 9 to 5. Breaks and miles driven. *not needed for this example because all the data I need is in the hourimport table.
users contains id, name, mail etc
echo '<br>STEP 1: <br>Connected successfully <br><br>';
$yesterdayT = date('Y-m-d', mktime(0, 0, 0, date("m"), date("d")-1, date("Y")));
$yesterday = date("Y-m-d H:i:s", strtotime($gisterenT));
$yesterday = "'$gisteren'";
//////////////////////////////////////////////////////////
$result = mysql_query("select id as employee from users inner join user_group on users.id=user_group.user_id where group_id=10 or group_id=11");
if (!$result) {
echo 'Could not run query: ' . mysql_error();
exit;
}
$rows = array();
while($rows[]=mysql_fetch_array($result));
echo "<br>A <--<pre>";
print_r ($rows);
echo "</pre><br><br>";
//////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
$result1 = mysql_query("select employee from hourimport INNER JOIN hourimport_detail ON hourimport.id=hourimport_detail.parent_id WHERE hourimport.date =$yesterday");
if (!$result1) {
echo 'Could not run query: ' . mysql_error();
exit;
}
$rows1 = array();
while($rows1[]=mysql_fetch_array($result1));
echo "<br>B <--<pre>";
print_r ($rows1);
echo "</pre><br><br>";
//////////////////////////////////////////////////////////
$result3=array_diff_assoc($rows,$rows1);
echo "<br>Users that didnt send in their dayreport<pre>";
print_r ($result3);
echo "</pre><br><br>"
This is what I have till now. And this works till so far.
Hourimport
id int(11) auto_increment
date datetime
employee int(11)
mail int(11)
status text
Assuming you have a table users with a primary key id column or something (and the user column is a number referencing users.id), and the day format is something that can be easily compared (for example date), you can do something like this:
SELECT * FROM users WHERE id NOT IN (SELECT DISTINCT(user) FROM hours WHERE day > :limit)
:limit is then a placeholder for the minimum day to filter against (I'm a Java guy and that's the syntax for JPA, for PHP I think it's $1 but you'll figure it out ^^)
First, you need a table of all the users who submitted their hours. Then you need a table of ALL the users.
What you would then do, is do RIGHT OUTER JOIN on the two tables. The resultset would give you the users who haven't submitted their hours mapped to nulls.

Select rows from MySQL where data is not the same

So i have a chat system and a topbar with notifications
What i want to do is load the last message from the last X persons the user has chatted
So i dont want to spam the notifications with X number of messages from the same person but i want to load the very LAST message from X number of persons
So here is my problem (example):
Imagine if one person sent the user 8 messages and i limit the message query to 8 results. The query will return 8 messages from the same person but i've made a PHP filter that will echo only 1 message from one person. So basically this will only echo 1 message from 1 person but wont echo any other messages from any other person because ive limited the result query to 8 and this user already spammed 8 messages
This is my PHP filter (but i want to do this in SQL)
foreach ($sideMess as $smes) {
if (!isset($showedList[$smes['id']])) {
echo '<div class="mes_wrap" id="ppl_', $smes['id'] ,'">
<img src="', $smes['avatar'] ,'">
<h4>', $smes['firstname'] ,' ', $smes['lastname'] ,'</h4>
</div>';
$showedList[$smes['id']] = true;
$cS ++;
}
}
As per your specification, it seems that you want list of last message from multiple users, i.e, user-wise last message.
select * from
(select * from
messages
order by user_id,message_time desc) temp
group by user_id;
Okay, its solved!
I used GROUP BY sender_id before ORDER BY
Thanks for your help!

Best way to alert user

I have a database with a table called userbadges . All users have all badges at level 0 "locked" (greyed out) . They can unlock it at level 1 , all the way to level 3. Each level is worth points.
userbadges {user_id,badge_id,level,score,seen}
What would be the best way for me to alert the user that they
a) have unlocked a new badge
b) have leveled up a badge
I have this code , but it doesn't seem right. It counts the number of new badges ():
function countNewBadges() {
require "connect.php";
$newbadges = mysqli_query($connection,"SELECT users.studentid, individualbadges.badgename, ub.level, count(ub.seen) as total FROM userbadges ub
INNER JOIN users ON users.id = ub.user_id
INNER JOIN individualbadges ON individualbadges.id = ub.badge_id
WHERE studentid = '".$_SESSION["studentid"]."' && seen=0 && level!=0") or die(mysqli_error($connection));
while ($data = mysqli_fetch_array($newbadges)) {
echo $data['total'];
}
}
I also have code to set the seen field of the badges table to 1.
I would make a messaging system: Create a table message with text, title. (for every message you have or dynamicly) Then make a table user_has_message where you got the 2 Keys to join, and a boolean if read.
With a simple Select * from user JOIN user_has_message on ... and iduser = ... JOIN message on ... where read = false you get all your alerts/Messages for a specified user.
EDIT: Now you can simply add an entry to user_has_entry, in which you specify which user should get which message.
Now you have much possibilities: add the date with default NOW(), to know when the message occoured, give the user the possibility to delete this message (what only deletes the entry on the user_has_message), add tho option to mark a message as unread, etc etc ...
Shure you can also use those messages for other things like a Welcome-Message etc. Or add a cronjob to send an email to the users with open messages older than 5 days. Or even implement a chat-system...

Echo the variable of i in while

i try something like this :
function userrank($userid){
$sql = mysql_query("SELECT * FROM users ORDER BY atacs DESC");
$i = 1;
while ($row = mysql_fetch_assoc($sql)) {
if ($row['username'] == $userid) {
echo 'You are on ' . $i . ' in the general leaderbord';
}
}
}
On the leaderboard it shows me the rank correctly, but i want to show me on another page too , on the "youraccount" page , for this i try to make this function.
what is wrong ?
Basically what you're doing here is counting how many users have an atacs greater than or equal to $userid's atacs. Problems with this:
Terribly inefficient. Note the database retrieves and sends to your
while loop an entry for every user, even those who have an atacs
less than the $userid. All but one of these while loop iterations
does nothing by design. Lots of wasted time sending data from the
database to PHP, which doesn't even use it.
Pulls way more data back
than is necessary. You end up with every row for every user in
your entire users table - but your result is just a scalar number
( how many users with > score ).
Actually gives you wrong results
in the case that your score is tied with others'. In this case some
users with the same score may be counted as "above" the user, others
as "below the users".
Databases are good at iterating over data; it's
all "locally" accessible and the database engine can make many
optimizations if you can describe in SQL what you are trying to
accomplish. So instead of doing it that way, why not just do
everything in the database?
set #user_atacs = ( select atacs from users where id = 12 );
select count(*) +1 from users where atacs > #user_atacs;
I've mocked up the table here: http://sqlfiddle.com/#!2/ff9a86/3
This solution essentially just counts the number of users with a higher atacs than the current user. All users with the same score will get the same rank, and the next rank will be appropriately higher, so it doesn't suffer from any of your method's errors.
As a final note, the most appropriate way to do something like leaderboards is probably to precompute the leaderboard periodically and then use the results to show each user's position in the leaderboards, rather than trying to compute it on the fly for each user. But that's even farther out of scope :)
You have to increment $i. I'm Assuming that the leader board order is represented by the result of your query. So, if true, change your code as follows:
function userrank($userid){
$sql = mysql_query("SELECT * FROM users ORDER BY atacs DESC");
$i =0; // starts out with an unknown rank.
while ($row = mysql_fetch_assoc($sql)) {
$i++; // increment $i here.
if ($row['username'] == $userid) {
echo 'You are on ' . $i . ' in the general leaderbord';
}
}
}
The $i will increment for sure. So, if it is not working still, I'd look to see what the result of your query is. Try echoing $row['username'] and see what the value is and then compare that to the echoed calue of $userid.

Categories