Notify user of new comments by email - php

I have a blog and I want to add a function "Notify me of new comments by email" to each post, when the user comments a post.
Im working with PHP and MySQL.
I was thinking about to send a mail to the users who has commented some posts and has checked the checkbox "Notify me of new comments by email" with a query like:
$query = mysql_query("SELECT COUNT(post_id) AS NumberOfComments FROM comments WHERE post_id = $post_id");
$row = mysql_fetch_assoc($query);
if($row['NumberOfComments '] > $NumberOfComments){
mail("someone#example.com","subject","message");
}
But if someone deleted a comment from the post and a new comment has been added then it would be the same number of comments and no mail will be sent. Any ideas on how the query could be better?

It depends on when you want to notify the user.
Do they want to be notified of every comment? Then the functionality which posts the comment would also send the notification. Any time a comment is posted, check for users to be notified and notify them.
Do they want a periodic (daily, weekly, etc.) notification that there exist new comments? Then you still don't want a count. What you want in that case is to check if there exist new records. There are a couple of ways to go about this:
Based on identifiers. If you know the ID of the last comment about which the user was notified (which you may need to store somewhere in a notifications table) then you check if there exist new IDs above that one. If so, there are new comments.
Based on date. If you know the timestamp of the last comment about which the user was notified (which you can store somewhere or calculate on the fly based on the period of notifications) then you check if there exist new comments since that time. If so, there are new comments.
As you've found, simply counting the records isn't a meaningful indication of what you're looking for. All a record count does is tell you how many records there are. If you want to know when those records were posted, you need a timestamp of some kind. If you want to know if records match previously known records, you need an identifier of some kind.
Never assume information derived from data which doesn't hold that information. Store the information you need to know.

Do this mailing on the insertion from the comment to the database, then you dont need this extra query.
EDIT:
So you store the user's who want to get notified in the database
with a table with a id user_id post_id i named it comment_notify
then you can do something like that
// Insert comment to database
$userWhoWantGetNotified = mysql_query("SELECT * FROM comment_notify WHERE post_id = $postId");
while ($entry = mysql_fetch_assoc($userWhoWantGetNotified )) {
$userId = $entry["user_id"];
// get email from user_id
mail(..);
}

Related

How to create a ticket reference number in PHP and mySQL

I'm working on a ticketing system in PHP and mySQL.
I have a table support with id as my primary key and AI.
I want to add ticket_number, so that when a ticket is submitted each ticket is assigned a unique number. I can't use mySQL to AI a second field, right?
If I give the first ticket a number, then write a query to lookup the last ticket_number in the DB, then I was thinking of doing something like:
$ticket = 1;
$next = $ticket+1;
echo "ticket number: #".$next;
would this work or is there a better way?
As advised by MonkeyZeus, you need to take a step back and rethink your schema.
You want to have multiple rows (replies) that are linked together by a single ID (the ticket number).
You definitely want this ID to be the ID of a row in another table.
So you should have two tables:
one for tickets
another for replies
The first one will be able to hold data that is ticket-specific, including the state of the ticket (open, closed...), who it is assigned to (the id of the user), who created the ticket (again, an id), and possibly when it was opened and closed (though this could be inferred through other means).
The second one will hold data specific to each entry in your ticket (the initial message, and subsequent replies going back and forth).
You may also have other tables (or it could be the same as replies) for other types of actions (ticket status changed, sub-ticket created, etc.).
tickets will have a unique ID which you can use as is as the ticket number (probably with some sort of prefix, possibly reformatted somehow).
replies will have a unique ID (which will be useful when you want to attach files to the reply, or edit it) as well as the ID of the ticket it is associated with.
Let Mysql create IDs. Use you favorite language's API to get the ID of the last inserted row.
DO NOT increment IDs client-side based on the max id returned by the server. Race condition looms.
DO NOT use IDs that are generated client-side and are not guaranteed to be unique
You can achieve by below code. It will generate unique ticket number every time
$brand = '#ref';
$cur_date = date('d').date('m').date('y');
$invoice = $brand.$cur_date;
$customer_id = rand(00000 , 99999);
$uRefNo = $invoice.'-'.$customer_id;
echo $uRefNo;
For a good and unique ID you have much better solutions :
You can use a md5 hash based on the microtime (same as uniqid from PHP but more secure)
You can use an extra column with unique = true functionnality and a request to get the max of this column and increment in your code before a new insert
You can use your support ID as unique entry, it's perfectly doable by inserting first the other field and then get back the ID inserted to update your ticket ID (if its a other component of your table) or show it alone to your users if you consider it as you ticket id..
#jcaron I've designed a schema - would this work?
I decided to adapt #Himanshu kumar's answer as follows (as it resolves my orgional question) to use the user's id and the timestamp (both of which I'm using already) as the ticket number:
$user_id = 7; //example from session variable
$cur_date = date('dmyHis'); //timestamp ticket submitted
$ticket = '#'.$user_id.'-'. $cur_date;
This will create create a unique variable that has the user's id and the date and time. I've used seconds to make it more unique. I will then use a query to find all messages/tickets with this ticket.

Ensuring users do not spam "like" button

My friends and I are creating a petition board and i'm adding a like/dislike function to it. I intend to make it such that only users can like/dislike it. Problem is, I do not know how to ensure that the users do not spam the button multiple times and how to register which user has liked/disliked which topic. Below is my code so far.
EDIT: Thanks I am creating the likes/dislikes table right now. But now I have to compare the users with the database to see if they have previously liked a comment. I know I have to use WHERE (to check both likes and dislikes table) but i am not sure how to combine it with IF.
<?php
include connect.php
if (isset($_POST['like']) || isset($_POST['dislike']))
{
if($_SESSION['signed_in']){
if (isset($_POST['like'])) {
$sql="UPDATE
topics
SET
likes=likes+1,
WHERE
id=topic_id";
echo "You liked it";
}
elseif (isset($_POST['dislike'])) {
$sql="UPDATE
topics
SET
dislikes=dislikes+1,
WHERE
id=topic_id";
echo "You disliked it";
}
}
else{
echo 'Please log in.'
}
?>
You should have a table of "likes" with the following columns.
"article_id", "user_id", the primary key should contain both columns
Every time a user likes an article, INSERT INTO likes VALUES($article_id, $user_id);
It will fail if someones Likes twice, thanks to the primary key.
Every time a user dislikes, DELETE FROM likes WHERE article_id = $article_id AND user_id = $user_id. That will allow the user to like again if he wants.
To get the number of Likes for an article, run a SELECT COUNT(*) as nb_of_likes FROM likes WHERE article_id = $article_id instead of storing the number in the article table.
Makes sense ?
The following solutions are possible, which can be used together:
If you use a registration/login mechanism, then you could internally setup some counting mechanism so each user can like once per petition (like Bgi suggested).
You could store a cookie, preventing him for further liking, even if he creates a new user.
Of course people can delete cookies or use other browsers, so you could hash their IP with e.g. md5 and compare the hash if that hash was already using the petition.
Of course multiple people can share the same IP, so IP hashing might not always be a good solution. Alternatively, you could use facebook API, and require that people have some amount of friends or something in order to verify their authenticy.
You will never fully be able to get rid of spammers, depends on how specific is your petition. Hence the more you want to prevent exploiting from using the petition, the less anonymous it will be.

Limiting activity via PHP

I have a social network that allows users to post blogs, ask questions, and message. We have had a slight issue with spamming. For example, we had users sign up, and write about 6 blogs a minute trying to sell stuff.
I am looking for a quick way to limit these activities by the id of the user, let's say only allowing them to post 3 blogs a day.
I have the users stored in a $auth variable and through OOP bring them up by $auth->id for example to be more specific.
Looking for a fast,simple way to do this via php.
thanks in advance /**EDIT*****/
this is what I have so far, and I know for sure $too many is counting as it should, but for some reason my if(statement is not stopping the 4th blog from posting. HERE is the code
Something like CAPTCHA would be appropriate. However, if they're being entered manually, it will do little to stop them. Regardless, no reason you can't implement both methods.
I'm assuming you have a created field in your blogs table. Simply query the table for the number of blogs with today's date before allowing another to be posted. Not sure what database/API you're using. In MySQL, you could do:
SELECT COUNT(*)
FROM blogs
WHERE user_id = USERID
AND DATE(created) = '2011-11-30'
When the user writes and submits a post, save the date they posted on the post's table. Select and count the amount of times they posted today. If they are under their limit, allow the post or else give them the error/warning message.
When a post is made, do something like:
// Get last post time and number of posts today from database
$query = "SELECT
last_post,
posts_today
FROM
users
WHERE
id = '$auth->id'";
$result = mysql_fetch_assoc(mysql_query($query));
// See if this is the first post today
$isNewDay = date('Y-m-d') != date('Y-m-d',strtotime($result['last_post']));
$postsToday = ($isNewDay) ? 0 : (int) $result['posts_today'];
// Only add post if user is allowed
if ($isNewDay || $postsToday < 3) {
/*
Add the post to the database here
*/
// Update the number of posts today in the database
$query = "UPDATE
users
SET
last_post = '".date('Y-m-d H:i:s')."',
posts_today = '".($postsToday + 1)."'
WHERE
id = '$auth->id'";
mysql_query($query);
} else {
echo "You have already made 3 posts today!";
}
...or you could just use a CAPTCHA (as mentioned by others). That's what they're for. Really, you should have one in the signup process...
I'll admit I know next to nothing on PHP programming, but another option (or addition to the CAPTCHA) would be to use a service such as StopForumSpam
There's an example of how to use it here (no idea how good it is, as I don't code PHP (yet)) :)

new comments notification implementation for a web site

I've got a website where people can make posts and comment on them. I want to make a new comment notification system, so when a user logs in he can see number of new comments to his posts.
My idea is to add a 'read' table, where I will store user_id and comment_id (means user_id read comment_id). But this can make some performance issue, when table will grow big.
What's the best way to implement this?
One way to achieve that is just to save a created date for post and comment, and a "last visit" date for the user (or "last time the user click on the "show me new post" link).
Then, you just need to get all the post and comment that have a newer date than the one you find in the user table.
How about just storing the user and comment IDs for unread comments instead? Then when the user reads the comment, you can delete that row from the table.
Wouldn't it be better to store the post time in the notifications table and then look for the user's last activity (again storing the value in the users table). Then you could do a simple query:
$lastActivityTime = User->GetLastActivity();
$result = mysql_num_rows(mysql_query("SELECT COUNT(`id`) FROM `notifications` WHERE `postTime` > '$lastActivityTime'"));
Good luck!
You can choose a different storage than mySQL for this data (Like : MongoDB).
Or you can make pub/sub implementation for notifying users. (With using pubsub you dont need to store data. Just notify)

PHP "You have () new comments on your clip", how?

I want to do a function to my users, so on index.php there is e.g:
You have 2 new comments on your clip
How should i do this? I mean i want ideas to do this the easiest way. Table for the videos is member_videos, and tables for the comment is member_videocomments, a comment inside the table is connected by their "videoID", which is the id of the column in member_videos.
Should i do the classic, making a field, which all is 0, until it has been seen by the user its 1 or what should i do.
One alternative to the unread flag on each comment is a last_read_comments timestamp on the user record. Whenever they read their new comments, update the timestamp to the current time. When they land on your homepage, query for all comments newer than that timestamp value.
Why don't you just do a check when you load the video against the comments table that says something like
SELECT COUNT(*) FROM member_videocomments WHERE videoID = videoIDLoaded;
Then get the result set back as an integer and check if that integer is equal to 0, if it is then display 0, else query the database for the comments get the result set back and display all the comments on the page however you like.
Just update a field in the table member_videocomments, something like readbyuser. Leave it at zero until the user views that specific comment.
$result = mysql_query("SELECT id FROM member_videocomments WHERE !readbyuser");
$num_rows = mysql_num_rows($result);
You've given the answer yourself. Just mark the comments when they are actually being displayed to the user. Assuming new comments are not viewed all at once but instead per video clip, I don't think the timestamp approach would be a good solution, because when you update the timestamp once the user has opened one of their newly commented videos, you will lose track of other new comments.
I have a similar situation, and I am using a is_read flag. When comments are added to the database, is_read is set to 0. When a user logs in, I check for any unread comments (it's here that I grab the # of unread comments so I can display it). Then when they view them, I grab the IDs of the comments and run a query to set their is_read to 1.
Matthew's timestamp solution is also good, so really it's up to what you feel more comfortable with.

Categories