Запрос MySQL, сравнивающий datetime

#php #mysql

#php #mysql

Вопрос:

На моей странице пользователь может зарегистрироваться по электронной почте и подписаться на новости. Я помещаю адрес электронной почты, IP и временную метку в свою базу данных. Я хочу убедиться, что один IP-адрес может получать только 5 электронных писем в день, и я не хочу, чтобы в моей базе данных были одни и те же адреса электронной почты.

Я пробовал это, но это не работает, я могу публиковать столько, сколько захочу.

 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";
}
  

И не для того, чтобы писать одни и те же электронные письма, я должен использовать что-то вроде этого после вставки?

ИЗ dual, ГДЕ НЕ СУЩЕСТВУЕТ ( ВЫБЕРИТЕ * ИЗ subscriber, ГДЕ email=»‘.$email.'» )’;

Ответ №1:

Почему бы вам просто не разделить запросы. Сначала проверьте

 SELECT count(id) FROM subscriber  
WHERE ip="'.$_SERVER['REMOTE_ADDR'].'" 
and DATE(`data`) = CURDATE()
  

И если результат < 5, тогда выполните вставку. Это будет просто и читаемо.

Весь код:

 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";
}
  

Будет хорошо, если вы разместите индексы по этим полям в БД.
Но я посоветую вам использовать PDO вместо mysqli. Вы можете прочитать больше об этом здесьhttp://php.net/manual/en/book.pdo.php

Комментарии:

1. Не могли бы вы, пожалуйста, написать мне весь запрос? Для меня это немного сложно: D

2. Да, спасибо, и еще одна вещь, которая мне нужна, это не записывать одни и те же электронные письма в базу данных… Проверьте мой отредактированный вопрос

3. Он всегда говорит, что электронная почта уже существует… Может быть, что-то не так с моей таблицей базы данных? Я действительно верю, что ваш код должен работать…

4. var_dump($mailExist) ?

5. Объект класса не может быть преобразован в int, его ошибка выглядит следующим образом

Ответ №2:

Вы не должны группироваться по электронной почте, когда хотите подсчитать все электронные письма с одного и того же IP.

Итак, ваш фиксированный запрос будет:

 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
    )
  

Вы также можете написать это другим способом

 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
    )
  

Или таким образом:

 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() 
    )