Best way to show an admin message to certain users? - php

I am building a social network site in PHP/MySQL/jQuery. Once a user is logged into my site, I would like to query the DB and get an admin announcement if one exist. This will be a message box that shows on the page to all users but it will have an X to click on it and not show it ever again until the admin post a new announcement message. So if you never click the X and there is announcement messages that exist in the db, it will always show this message box on your page, however if you did cli9ck the X to close the box, then you come back to the page it will not be there, unless there is a new admin message posted.
I know there is several ways of doing this but I am looking for the most efficient way.
One idea I have, if I add an extra mysql field onto the user's table "admin_message" and mark it as 0, then when I post a new admin message it will change the record for every user to 1, if admin message is set to 1 then it shows on user's page. Then when the user clicks the X to hide the box, it will update there user table row and chnage the value back to 0.
Another idea I have is to use cookie's to check if a user has chosen to hide a message, i think this would be faster but maybe not as good, since user can log in with differnt computers and if a new message is shown, they may not see it right away.
So I am just wondering if it is a bad idea to use the extra database field? If I had 1,000,000 users, when I posted a new admin message, then I would need to update 1,000,000 rows to make sure everyone can see the message. Is there a better way? Also once a user logs into my site I will use a session to store the value of them seeing or hiding the message instead of looking at the DB on every page load.
UPDATE
Sorry I think my post might of been a little confusing or not clear on what exactly I meant because most the responses are catered to a message system which this is not anything close to.
Forget the message word please I will try to explain with a different word. Let's say there is 1 admin on the site, that is the only admin who can post a message to users to see. The users will only see 1 message, if there is 2352345234 messages posted over the lifetime of the site, it won't matter, they will only see 1 message, the newest message.
Now some users who log in and see this message "div" on the page might get tired of looking at it, so they will be able to hide it from ever showing again.
It will be as simple as a yes or no for showing this message on there page.
However if I decide I need to post a new admin message for all users to see, then even a user who chose to hide and not show the admin message will still see it again until they choose to never see it again.

Two simple solutions are as follows:
Good: Check the users cookie, if it contains a flag indicating the message was displayed don't display the message, otherwise display it. When the user closes it, update the cookie. Pros: absolutely simple. Cons: The user might see the same message twice depending on if they clear their cookies or log in from another machine.
Better: Store a flag in the database somewhere (you can store it in the admin user table for now, and down the line break it out into another table). When the user logs in, 1) save this flag to the user's cookie or session, 2) update the database, 3) decide whether the message needs to be shown. When the user closes the message, updare the cookie/session and DB. Pros: User never gets shown the message twice. Cons: slightly more involved as you need to maintain the flag in the db.
Implementation details:
For the flag, you could use a message id as suggested already, or more than likely you are already retaining the user's last login timestamp and could use that.

Every user could have a last_message_seen, so you have to query "new" messages (message_id > last_message_seen) for your user. If you [X] close (or timeout), then your javascript can check new messages and so on...
The other idea is to have that last message seen number in the javascript environment, but in that case it will be reseted (recalculated) when you refresh/abandon the page, and if it's not on the DB your user can miss messages inserted between last page load and this refresh.
Or... it can be in the Session, so you don't miss any. When you logon, the number is reseted to some "normal" number, let's say: last message, or message after (now - 1h), or whatever...

You are keeping a login time for the user right? Like a last_login datetime?
So get all messages where date_created >= last_login. Display them, then update the last_login time to now().

I would use idea #1. I wouldn't use a bool-field to check whether the user has read the message, I'd use a datetime-field, with some default value. If field == default, unread. When read, set field NOW().
That way you know aproximately how fast your users read the message.
EDIT:
after your edit, I'd still use the same mechanism. The message needs a field to find out whether or not is read. If the users clicks the X (to close), update the db and mark the message as read.
If the admin posts a new message, this will popup.
You also need a creation-datetime for your messahe, cause if a user did not close the previous message, and the admin posts a new one, only the latest message can be shown.
EDIT2:
In reply to this comment:
Even if a user missed am message, only
the newest should be shown. Maybe I am
misunderstaning but it sounds like you
are saying to basicly mark a message
read 100,000 times is 100,000 users
click the X and I think it should be
more on the user table, show or do not
show message box, not on an individual
basis
something is not locigal in your theory. You want to save the "show/don't show" as a setting, but you want to show the message anyway. How do you know when to overrule the usersetting and when not without remembering whether the system showed the message to the user?
Even if you want to just show it once, you'll need a field in the database (on message-level) to store whether the system showed the message to the user or not.

I'd recommend having a admin_message_queue table. It'll have a message body, a user ID, and a message ID. When you post a new admin message it'll add a record for every admin user to that table. Then when they log in you simply select all admin_message_queue rows where user ID = the logged in user.
To get rid of the message you'd just have the close button trigger an AJAX callback to a method on the server that takes the message ID. That method will delete from admin_message_queue where message ID = the one posted in and user ID = the user ID from the session. That way a user can't delete messages for someone else.
Doing it this way saves you from having to keep around rows of viewed messages. Why toggle a bit to hide it for someone? You'll end up keeping around lots of data that's no longer used.
Updated after question update:
Sorry I thought you were trying to show messages to just admins. You could keep this same logic for displaying the most recent message to all users, too. Simply have a table with a userID, message text. Whenever you post a message it will go through and overwrite the message text for all people that have records still existing (people who haven't hidden the message) and add rows for other people. When they hide the message delete that user's row.

Related

Detecting page reload after clicking back button in PHP

I am looking for a way to detect when a page is reloaded after clicking the back button, so I can selectively ignore errors. Let me explain why:
Imagine a page that displays some data, identified by an id:
/show/some/data?id=5
Initially, the id exists and the page is displayed. If the id does not exist, an error message is shown and an error is logged, because that should not happen and would indicate a broken link in the application.
Now imagine the user looks at the data, decides to delete it, and after deleting, uses the back button to go to the same page again (BTW this is not a hypothetical, I have seen this in my application). Now, the id is no longer valid, triggering an error. If I could distinguish between the initial page load and the second page load after using the back button, I could be more lenient in my error handling. My reasoning being that a broken (forward) link in the application is a fatal error. A broken link after clicking back (when there was none initially) is very likely caused by some action the user took in the meantime. In that case I would much rather redirect the user to an overview page than show an application error.
I believe one way to solve this would be to attach some randomly generated id to the url:
/show/some/data?id=5&rnd=<?php print rand(); ?>
and log the random ids that have been used in the session. If an id repeats itself, I can assume that the page has been reloaded, and selectively ignore some errors.
However, that would require altering many links in the application. I could also use javascript/jQuery to alter all links on the page to the same effect:
$("a").attr('href', function (i, h) {
return h + (h.indexOf('?') != -1 ? "&" : "?") + "rnd=" + Math.random ();
});
That's slightly less invasive, but still rather heavy handed for solving such a seemingly trivial problem. I wonder if there is or can be a self-contained way to do this. Is there any way for the backend application to distinguish if a page is loaded by forward clicking on a link or reloaded after clicking back? Or is there a more elegant solution with javascript?
There's no perfect solution for this since you're trying to (sort of) change a browser's behaviour. The simplest idea I can think of is setting a session variable with a list of deleted pages, and pushing the page IDs into it on the delete page.
Then, you need to update your error handler to additionally check for the presence of the requested page ID in the deleted pages list. That way you won't have to mess with URLs at all.
Here's an example flow:
user requests page id 1
app checks the db, it doesn't exist
app checks the session, it's not in the deleted pages list
error message shown, error logged on the server
user requests page id 2
app checks the db, it exists, show the page to the user
user clicks the delete button
ID of the page is added to the session list of deleted page and the page is deleted
user goes back (or types the url manually, this is a bonus feature)
app checks the db, id 2 doesn't exist
app checks the session, id 2 IS in the deleted pages list
error message shown, no errors logged
You can also take this one step further and track all the visited pages, so you'll know that if something was there a few minutes ago, and now it isn't, the user must have deleted it. This would allow you to handle more such events if needed.

disable multiple voting on user comments

Description:
I am creating comment/reply functionality to a web app that I built. I have a post that I want to link these comments too. To decrease spam and encourage community involvement I want to implement a voting system on each comment/reply.
Problem:
I know how to set up the database and I know how to show upvotes/downvotes. The only thing I don't know what to do is to keep the vote... voted even if the user refreshes the page. I don't want a user to be able to vote up more than once on a single post. Something like the voting on this site, it tracks that you have already voted with a yellow upvote.
What I have thought of:
Place post id in cookie with the user_id appended to it. A simple check of the cookie can stop the user from voting again
Place a unique constraint in table post id... but this is where I get confused. Should I have a separate table just for voted posts? Database schema idea ( I think ) here: https://stackoverflow.com/a/12350981/185672
Keep all the ids in a session array and check against all voted on ids... but that would get huge.
Combination of cookie and database to reduce number of db calls.
In the future there may be 1000s of votes cast by a single user.
edit:
I figured out that storing the results in a database is a must. How can I check for every reply/comment if the user has valid voting privileges without making 1000s of calls?
Resources:
Helped with some further spamming problems, but didn't answer initial question:
https://stackoverflow.com/a/2333085/185672
Old solution that explains how to count votes but not keep the "upvote" checked.
http://www.9lessons.info/2009/08/vote-with-jquery-ajax-and-php.html
Bonus question:
If you guys know of a great script that can allow me to sync up a commenting system ( with votes ) into my already built app?
Also, I tried to find duplicates, but I just can't.
Yeah, just keep a separate table to track user votes. Since you know which user is requesting the page, you can easily join the votes table to determine the current user's eligibility to vote on each post on the page. For each post, if they're eligible, output one version of html, if they're not then output another.
Once the ajax request asks for the php file that does the vote, you can then check once more that that user is eligible to vote - I.e they're changing their vote, or they haven't voted before.
Take yahoo's news stories for example - when you request a page that you've made a comment on, your own comment has disabled voting buttons. With some hacking of the page inside the browser's dev tools, you can enable the buttons. You can even click on them and vote for your own post - though only once.
So, you can see that they got 2/3rds of it right, and output html based on the user's eligibility to vote. They also prevent multiple voting (server-side), they just don't do a server-side check to ensure you're not voting for your own comment.
Stack Overflow on the other hand, always shows the same html - but when you click to vote for your own comment, the server-side code baulks at the idea and the response is basically 'bugger-off! you can't do that' having received a negative result from the server, the javascript on the page pops up the message, rather than updating the vote count.
I suggest you create a "hidden field" in your page that stores information about the upvote/downvote by the user. This is how you would use it:
If the user upvotes/downvotes, the javsvscript on the on the shows the upvote, sets the field to maybe true to indicate the vote status and would also send an AJAX request to the server where the server would record the vote status in the user profile database.
Then whenever the post is re-loaded for a particular user, the server sets the hidden field server-side to true or false, depending on the vote record that is stored in the database. The JS would, on load, check the hidden field and set the vote on the page accordingly (you might need an extra hidden field to indicate whether it is an up or down vote).

Most efficient method to check whether user has new mail?

I have a simple and generic internal messaging service on one of my PHP/MySQL sites, with a unique messageID, from, to, subject, message, time, and isRead.
In general, what is the best way to check that a user has new mail?
Should I store a simple binary trigger on the main Users table that gets switched to 1 when anyone sends them a message, and then have the user check for that 1 on every pageload, and if there is one, alert them to the new mail (and set it to 0 whenever they go to their Inbox)? But what if it was spam and we deleted it before the user read it?
Or should I store the messageid of the last message the user read, and then do a check for the latest message and see if it's more recent than the last one that he read, and if so alert him? But then how and where should I store this info?
Is there another, more efficient method considering we would have to check for new messages on every pageload?
If the user goes to his Inbox, it should no longer show him that he has "New Mail" for any of the messages that were in his Inbox at the time he checked it, regardless of whether he's actually clicked to read them or not.
Thanks!
EDIT: Some of my users access my site from very basic phones that don't have cookies or even Javascript, so please keep that in mind.
Best way would be push notification from server, like stackoverflow does, using html sockets.
jquery plugin
But keep in mind that is not supported by all browser, so will need to fall back to ajax polling.
About spam i would suggest only notify user after spam checking if done, if possible.
Your solution to store next to user with set bit sounds right, (also you could store number of new message, instead of bit)
In your users table, store the count of new messages, and update when needed.
AJAX polling can be expensive in serverside (the select count(*) from ... can be expensive when your DB became large, and you need to do it, for example, one check per minute).
If the user just browsing in your website, and have no new messages, you can just skip select more information about messages.

Soft Delete VS Hard Delete

I am building a system that will use a commenting based ticket system. I would like to get some opinions around the idea of flagging a user as deleted or removing the record completely.
Ideally I want to keep the system free of old accounts but at the same time by deleting a user the commenting within the ticket system may not make sense.
Has anyone come up with a solution to this type of problem. My ideas so far:
Delete the users account, comments and all other relevant data.
Flag the user as deleted and create a brand new account if they subscribe again.
Flag the user as deleted but if the user was to try to subscribe again update and unflag as deleted instead of adding a new one.
Delete the user account only. Then when fetching comments etc. check for an associated id, if no result found then display the comment with a message "the users account has been deleted".
What do you think?
I would say that the third option is the best choice
My reasoning for this is any tickets stored in the database should be kept for the life of the database, if you attempt to delete a user from the database, you will remove that users reference to any tickets in the database.
(Thats if the database will let you delete it since the user's id will be linked to any tickets he/she may have created)
When that user goes to create a new account in the ticketing system, the tickets that he may have created months ago have dissapeared and may now have been created by null.
I would always use the last solution: delete the user account only and show an "account deleted" message if the poster's account doesn't exist anymore. If you don't allow users to change their username, you can also save the poster's username (beyond his ID) and display it as plain text if the user deleted his/her account, or as a link if the user is still active.
If you're representing the user <-> comment relationship with a FOREIGN KEY, you can't delete the user without deleting the comment or updating the comment's associated user to either NULL or to point to some "deleted user" fake user account (in either case, losing the information about the user who posted the comment).
The ticketing system I wrote basically did number 3. Anything else will ruin any audit trails you need to keep.
If you need to get rid of old stuff one way is to set cleardown of old tickets. Then, when all related tickets for an account are gone, you can remove the account.
It really depends on you use case.
Personally I would never delete stuff like user-accounts from a db completely.
So option 1 is out. (but that's just me)
Option 2 has the problem, that you'll have lots of dangling user-accounts.
Option 3 looks like the best option -cough- audit trail -cough-
Option 4 is asking for trouble, you have a link to another table, but that data has been deleted.

alert who is already reading this page in php?

We have a back end application to manage messages from our clients. We have 4 customer care executives and we want to prevent the situation where the same message can't be opened by two different members, so we would like to do following...
Suppose user1 opened message id 15 and after that user2 opens same message, so we would like to give a alert that 'This message is already opened by user1'. How do we do it?
Create a different table in your database.
When a user opens a message, update the table to show which message has been opened and by which user.
When another user tries to open it, crosscheck the table to see if there is a row for that message. You can then do the appropriate action such as open or warn the user.
You can delete the rows after a given timeout period to allow others to open.
Schema eg
User_id msg_id time_opened
Unfortunately, you can't use sessions since the sesssion is user specific. However, you can employ flatfiles.
To delete the rows, employ a method such as
$timeout_time_in_seconds = 30;
$time = time() - $timeout_time_in_seconds;
$Query= "delete from table where time_opened
Note that depending on the time field, which can be an int, datetime or timestring, additional date formating of the $time variable may be required. However, int will be most convenient due to ease in comparison and subtraction and no formatting.
I'm mobile so pardon any errors. Also that's why I didn't comment but had to edit. Js issues.
What happens is, when the first user clicks, a quick check and update of the database is made.
When the second user tries, the script will detect the first user has already opened by checking the database.
You can count on this to work if the traffic load is low and the number of users trying to access is not too great. And also counting on the fact that the read and insert queries occur in a short time which as you can Guess is faster then two users clicking at the same time. Unless you have another issue, this should work
Simpliest way would be to implement as pessimistic locking at the DB level
http://www.blackwasp.co.uk/PessimisticLocking.aspx
Whatever language you are using should let you check the DB to see if a row is locked or not and send a message on the screen.
You can additionally setup your application with long polling to notify users when the request resource has become available. http://en.wikipedia.org/wiki/Push_technology

Categories