Creating Message System in PHP - php

I m trying to create message system where I want to list down the users with whom one has interacted with recent chat on top I know this question is duplicate as well but i cant figure out where the problem is
Here is my message table structure
user_message table
msgID sentBy sentTo message sentTime
1 3 1 Hii B 1493306882
2 3 1 Hi A 1493309615
1 1 3 Hmm 1493306882
2 1 3 Yeah 1493309615
and the query i tried is
QUERY
SELECT * FROM user_message_status LEFT JOIN users ON user_message_status.userID=users.userID
LEFT JOIN user_message ON user_message_status.msgID=user_message.msgID WHERE user_message_status.userID='".$_SESSION['userid']."'
GROUP BY user_message_status.msgID ORDER BY user_message.msgID DESC
PROBLEM:
1) When userA send msg to userB, userA name is printed in chat list instead of recipient(userB)
2) The amount of msg sent or receive equals to the number of users are listed in the chat.
user_message_status: table
msgstatusID msgID userID box read readTime
1 1 3 outbox 0 0
2 1 1 inbox 0 0
This is status table to read unread messages or delete

First update the query to the below:
SELECT *
FROM user_message_status s
LEFT JOIN users u USING userID
LEFT JOIN user_message m USING msgID
WHERE s.userID='".$_SESSION['userid']."'
GROUP BY user_message_status.msgID
ORDER BY user_message.msgID DESC
Because both tables have the same column names, to make you sql shorter and neater, you can use the USING function
Both LEFT JOIN users ON user_message_status.userID=users.userID and LEFT JOIN user_message ON user_message_status.msgID=user_message.msgID was changed. We then renamed the tables to just a single letter so you don't have to write the entire table name.
Also why your userA is sent is because, your query will return, lets say I am id '3',
msgstatusID msgID userID box read readTime
1 1 3 outbox 0 0
So from the joins, the user_message will return
msgID sentBy sentTo message sentTime
1 3 1 Hii B 1493306882
1 1 3 Hmm 1493306882
So you would have to use an if statement or turnary operation for the name and say:
if (sentBy == $_SESSION['userid'])
$name = sentTo;
else
$name = sentBy;
OR
$name = (sentBy == $_SESSION['userid']) ? sentTo : sentBy;
Basically to show the proper name of who you are talking to, you need to first check which column name to use
AS for problem 2, if you want to limit the amount then you need to add more condition. Maybe you only want outbox so you need to put AND box = 'outbox'
The below sql should help you out
SELECT
s.msgId
, m.message
, (
SELECT CONCAT(firstName, ' ', lastName)
FROM users
WHERE userId = CASE WHEN m.sentTo = s.userId
THEN m.sentBy
ELSE m.sentTo END
) AS chatWith
, m.sentTime
, s.read
FROM user_message_status s
LEFT JOIN user_message m USING (msgID)
WHERE s.userID='".$_SESSION['userid']."'
ORDER BY m.msgID DESC
Remove LEFT JOIN users u USING userID because it will be sub queried
s.msgID // used for deleteing the chat conversation
m.sentBy, m.sentTo, m.message, m.sentTime // all important data for your messages

Related

mysql- get number of occurrences

Hi i am trying to get a mysql query working and need some help. I have 2 tables (staff, booking).
Staff table contains staff details
StaffID
First_name
Last_name
1
John
Doe
2
Mary
Doe
Booking table contains
BookingID
StaffID
Status
1
1
cancelled
2
1
cancelled
3
1
confirmed
4
2
cancelled
5
1
confirmed
I would like to get the count of confirmed/cancelled bookings for each staff but is having trouble getting it to work. My current query that I'm using is
Select staff.StaffID, staff.First_name, staff.Last_name, sum(booking.Status LIKE '$status') as Status
from staff, booking
where staff.StaffID = booking.ConvenerID
group by staff.StaffID
$status being cancelled or confirmed. With this query I'm only able to display a row if there is a status value, if a staff have no cancelled it does not display the row for that staff. How can I get the row to display even if the count of $status is 0.
You need a LEFT join of the tables:
SELECT s.StaffID, s.First_name, s.Last_name,
COALESCE(SUM(b.Status = ?), 0) AS counter
FROM staff s LEFT JOIN booking b
ON s.StaffID = b.StaffID
GROUP BY s.StaffID;
Replace ? with the status value that you want (there is no reason to use the operator LIKE because a simple = works fine).

MySQL: AND operator doesn't work

I have chat database contains from three table (users,message,message_recipient)
and their relations here :
Database Design
the content of table is :
tabel users:
us_id username password
1 user1 pass1
2 user2 pass2
3 user3 pass3
table mesasage
id msg_body create_date creator_id
1 "Hi user2" --------- 1
2 "Hi user3 --------- 1
table message_recipient
id repient_id message_id is_read
1 2 1 0
2 3 2 0
my problem is when select the messages that user1 send to user2 the AND operator not working or there is bug with AND
the SQL Query :
SELECT message.id, message.msg_body,message.creator_id,message_recipient.recipient_id
FROM message,message_recipient
WHERE message.creator_id='1' AND message_recipient.recipient_id='2'
the output is:
id msg_body creator_id recipient_id
1 "Hi user2" 1 2
2 "Hi user3" 1 2
You need to use JOIN to do that:-
SELECT message.id, message.msg_body,message.creator_id,message_recipient.recipient_id
FROM message JOIN message_recipient ON message.id = message_recipient.message_id
WHERE message.creator_id='1' AND message_recipient.recipient_id='2'
Note:- When you are trying to get data from two or more tables then you need to use different types of Joins.
Reference:- https://www.w3schools.com/sql/sql_join.asp
You need to join them on message id. Try this:
SELECT m.id, m.msg_body, m.creator_id, mr.recipient_id
FROM message m
JOIN message_recipient mr on m.id=mr.id
WHERE m.creator_id='1' AND mr.recipient_id='2'
I added this in where clause message.id = message_recipient.message_id in your code and it's works
we can able to join multiple table using where clause .
SELECT message.id,
message.msg_body,message.creator_id,message_recipient.recipi‌​ent_id FROM
message,message_recipient WHERE message.id = message_recipient.message_id and
message.creator_id='1' AND message_recipient.recipient_id='2'

Select from three tables

I have three tables where table_2 is the middle(connected) between table_1 and table_3
tables
table_id
...
...
table_rest
rest_id
table_id
...
rest
rest_id
...
...
And the query to select I use
SELECT m.table_id, table_name
FROM tables m
JOIN table_rest mr
ON m.table_id = mr.table_id
WHERE rest_id = '$rest_id'
What I need now is to join in this query another table reserv
id
...
status
To check if status is 0, 1,or 2 to not show me anything if there is no status this mean there is no record to show me. In other words this is resserved system where I show on screen few tables. If status is 0,1,2 thats mean the table is taken. If nothing is found for status this mean that there is no record for table and can be shown to user.
EDIT: Sample scenario
tables
table_id
1
2
3
4
5
rest
rest_id
1
2
table_rest
table_id | rest_id
1 2
2 2
3 2
4 2
5 2
So the query that is above will generate 5 tables for rest_id=2 and none for rest_id=1
So now I have another table
reserv
id | status
1 0
2 1
3 2
So in this table reserv currently are saved 3 tables. The idea is to show me other two whit id=4 and id=5 because they are not in table reserv and don't have any status.
Hope is a little bit more clear now.
You have to point from table reserv to which table is beign booked, let's call it reserv.table_id
SELECT m.table_id, table_name
FROM tables m
JOIN table_rest mr
ON m.table_id = mr.table_id
left join reserv
on reserv.table_id = m.id
WHERE rest_id = '$rest_id'
and reserv.status is null (*note)
*note use 'is' or 'is not' depending of your needs, as far as I read, first seems that you want !=, later that what you want is =
It's better if you provide sample data or sqlfiddle. Based on what I realize: Is this what you want:
select tables.table_id, rest.rest_id
from tables
left join table_rest on table_rest.table_id = tables.table_id
left join rest on rest.rest_id = table_rest.rest_id
where rest.rest_id = '$rest_id'
and tables.table_id not in (select id from reserv)

SQL query for fetching friend list

I need help with SQL query.
I have two tables. One is users and other one is userfriends
users table:
aid email firstname
1 example#mail.com example
2 example2#mail.com example2
3 example3#mail.com example3
4 example4#mail.com example4
userfriends tables:
reqid email friendemail status
1 example1#mail.com example2#mail.com 1 (example1 is frnds with example2)
2 example2#mail.com example4#mail.com 2 (example2 request pending)
3 example3#mail.com example1#mail.com 1 (example1 is frnds with example3)
4 example4#mail.com example1#mail.com 1 (example1 is frnds with example4)
So when status is 2 the add request is pending and at status 1 they are friends. What i want is that i want to retrieve the complete friendlist for user example1. I want to pull out names from users table for corresponding output from previous query to display as friendlist.
I think you guys are missing the fact that the searched for email could be in either column:
select u.firstname
from userfriends f, users u where
u.email='email#domain.com' and f.status=1 and
(u.email = f.email and f.friendsemail='email#domain.com')
or
(u.email = f.friendsemail and f.email='email#domain.com')
select distinct friendemail
from userfriends f
inner join users u on u.email = f.email
where f.status = 1
and u.firstname = 'example'
You need to JOIN both tables:
SELECT users.firstname
FROM userfriends UF
JOIN users U ON (U.email=UF.friendemail)
WHERE UF.email='your user'

MySQL & PHP: Send emails to the members who fall into last 3 active threads

My query below will get the last 3 active threads from my blog's commnets,
SELECT ID, Approved, RecipientID, RecipientScreenname, RecipientEmail
FROM
(
SELECT
root_strings.str_id as ID,
root_strings.str_approved as Approved,
root_strings.mem_id as RecipientID,
root_members_cfm.mem_screenname as RecipientScreenname,
root_members_cfm.mem_firstname as RecipientFirstname,
root_members_cfm.mem_email as RecipientEmail
FROM root_strings
LEFT JOIN root_members_cfm
ON root_members_cfm.mem_id = root_strings.mem_id
WHERE root_strings.parent_id = '1'
AND root_strings.mem_id IS NOT NULL
UNION ALL
SELECT
root_strings.str_id as ID,
root_strings.str_approved as Approved,
root_strings.mem_id as RecipientID,
root_users.usr_screenname as RecipientScreenname,
root_users.usr_firstname as RecipientFirstname,
root_users.usr_email as RecipientEmail
FROM root_strings
LEFT JOIN root_users
ON root_users.usr_id = root_strings.usr_id
WHERE root_strings.parent_id = '1'
AND root_strings.usr_id IS NOT NULL
) SQ
ORDER BY ID DESC
LIMIT 0,3
It returns a result like this,
ID Approved RecipientID RecipientScreenname RecipientEmail
14 1 3 x x#yahoo.co.uk
13 n/a NULL y y#yahoo.co.uk
13 n/a NULL y y#yahoo.co.uk
Then I will an email to each of them.
foreach($items_thread as $item_thread)
{
$sentmail = mail($item_thread['RecipientEmail'],$email_subject,$email_content,$email_headers);
}
But the logic is not correct when you look closer as I will send y twice of the email!
y should just get one email. How can I fix it - should I fix the sql query or the php code?
The problem is that NULL!=NULL (nor is NULL=NULL), so DISTINCT does not consider the 2nd and 3rd results to be the same. If you change your query so that RecipientID shows as 0 (e.g COALESCE(RecipientID,0) AS RID) the problem will go away.
I have a solution for this now which is using array_unique, here it is Remove duplicate items from an array

Categories