Reputation: 61
In my page user can register with email and subscribe for news. I'm putting email, IP and timestamp into my database. I want to make sure that one IP can only get 5 emails per day and I don't want the same email addresses in my database.
I tried this but it doesn't work, I can post as many as I want.
if(isset($_POST["send"]))
{
$email = test_input($_POST['email']);
if (!filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
$query = 'INSERT INTO subscriber (data, ip, email) (SELECT CURRENT_TIMESTAMP, "'.$_SERVER['REMOTE_ADDR'].'", "'.$email.'" FROM dual where NOT EXISTS ( Select count(email) as c FROM (
SELECT email FROM subscriber WHERE ip="'.$_SERVER['REMOTE_ADDR'].'" and DATE(`data`) = CURDATE() group by email) as a having c>5))';
$result = mysqli_query($dbc, $query) or die(mysqli_error($dbc));
$msg="E-mail sent successfully";
} else
{
$msg="Wrong e-mail address";
}
And not to write same emails i should use something like this after insert?
FROM dual WHERE NOT EXISTS ( SELECT * FROM subscriber WHERE email="'.$email.'" )';
Upvotes: 1
Views: 67
Reputation: 2029
Why don't you just separate the queries. First check for
SELECT count(id) FROM subscriber
WHERE ip="'.$_SERVER['REMOTE_ADDR'].'"
and DATE(`data`) = CURDATE()
And if the result is < 5 then do the insert. It will be simple and readable.
The whole code:
if(isset($_POST["send"])){
$email = test_input($_POST['email']);
if (!filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
$query = 'SELECT count(id) FROM subscriber
WHERE ip="'.$_SERVER['REMOTE_ADDR'].'"
and DATE(`data`) = CURDATE()';
$result = mysqli_query($dbc, $query);
$count = mysqli_fetch_field($result);
if($count < 5) {
$query = "SELECT id FROM subscriber
WHERE email='".$email."'
LIMIT 1";
$result = mysqli_query($dbc, $query);
$mailExist = mysqli_num_rows($result);
if($mailExist > 0) {
$msg="E-mail is already existing in the DB";
}
else {
$query = "INSERT INTO subscriber (data, ip, email) VALUES (CURDATE(), '".$_SERVER['REMOTE_ADDR']."', '".$email."')";
mysqli_query($dbc, $query);
$msg="E-mail sent successfully";
}
}
else {
$msg="5 emails today";
}
}
else {
$msg="Wrong e-mail address";
}
It will be good if you put indexes on this fields in DB. But I will advise you to use PDO instead of mysqli. You can read more about it here http://php.net/manual/en/book.pdo.php
Upvotes: 2
Reputation: 31792
You should not GROUP BY email, when you want to count all emails from the same IP.
So your fixed query would be:
INSERT INTO subscriber (data, ip, email)
SELECT CURRENT_TIMESTAMP, {$_SERVER['REMOTE_ADDR']}, {$email}
FROM dual
where NOT EXISTS (
Select count(email) as c
FROM (
SELECT email
FROM subscriber
WHERE ip={$_SERVER['REMOTE_ADDR']}
and DATE(`data`) = CURDATE()
) as a
having c>=5
)
You can also write it another way
INSERT INTO subscriber (data, ip, email)
SELECT CURRENT_TIMESTAMP, {$_SERVER['REMOTE_ADDR']}, {$email}
FROM dual
where NOT EXISTS (
Select count(email) as c
FROM subscriber
WHERE ip={$_SERVER['REMOTE_ADDR']}
and DATE(`data`) = CURDATE()
having c>=5
)
Or this way:
INSERT INTO subscriber (data, ip, email)
SELECT CURRENT_TIMESTAMP, {$_SERVER['REMOTE_ADDR']}, {$email}
FROM dual
where 5 < (
Select count(email) as c
FROM subscriber
WHERE ip={$_SERVER['REMOTE_ADDR']}
and DATE(`data`) = CURDATE()
)
Upvotes: 1