За последние 24 часа нас посетили 17667 программистов и 1280 роботов. Сейчас ищет 1421 программист ...

Проверка на наличие данных в БД при регистрации

Тема в разделе "PHP и базы данных", создана пользователем anvyd, 2 июн 2015.

  1. anvyd

    anvyd Новичок

    С нами с:
    17 апр 2015
    Сообщения:
    13
    Симпатии:
    0
    Допустим, есть таблица users
    В ней поля: first_name, last_name, phone, email, login, password
    я пишу скрипт регистрации, делаю проверку на заполненность всех полей формы, если все заполнены, я проверяю не занят ли такой логин в БД.
    Формирую запрос
    Код (PHP):
    1. $sql = "SELECT id from users WHERE login = '$login' LIMIT 1";
    2. $res = mysqli_query($link, $sql);
    3. $row = mysqli_num_rows($res); // Если занят, то придет '1', если свободен, то придет '0'
    4. if ($row) {
    5.     // создаем в сессионном массиве рег элемент со описанием ошибки
    6.     $_SESSION['reg']['res'] = "<p class='error'>Такой логин уже занят, пожалуйста, придумайте другой логин</p>";
    7.  
    8.     // Создаем сессионные переменные, чтобы пользователь не вводил заново данные
    9.     $_SESSION['reg']['first_name'] = $first_name;
    10.     $_SESSION['reg']['last_name'] = $last_name;
    11.     $_SESSION['reg']['phone'] = $phone;
    12.     $_SESSION['reg']['email'] = $email;
    13. }
    14.  
    в else я, естественно, уже провожу регистрацию(хеширую пароль и так далее)...
    так вот, в чем вопрос, как мне правильнее все организовать, если я хочу проверить не только логин, но и email, телефон, чтобы в БД не было одинаковых email и phone, мне необходимо делать два отдельных запроса на наличии email и phone и выводить соответствующие ошибки? или как это вообще делается? Направьте пожалуйста
     
  2. mr.akv

    mr.akv Активный пользователь

    С нами с:
    31 мар 2015
    Сообщения:
    1.604
    Симпатии:
    206
    1. делаете запрос на существование в бд любого из полей
    $sql = "SELECT * from users WHERE login = '$login' OR emeail = '$email' OR phone = '$phone' LIMIT 3";
    потом в скрипте смотреть данные, что пришли, и уточнять, какой именно из параметров совпал. А может совпало и несколько. Не очень мне нравится.
    2. можете сделать как у вас, но с тремя запросами.
    3. А можете переделать на AJAX, повесить на input событие onchange.
    Т.е. пользователь вводит данные, сбрасывает фокус с инпута (переключается на другой инпут, допустим), срабатывает событие onchange, отсылается аякс-запрос к скрипту.
    Допустим, ввели данные в поле логин, уходит аякс-запрос на freeLogin.php, в последнем делается запрос к бд, проверяется логин (ну как у вас сейчас), и возвращает результат.
    Преимущества:
    1. без перезагрузки страницы
    2. можно СРАЗУ уведомить пользователя, что логин и тд заняты (а не вводить все поля, потому нажимать кнопочку "отправить" и только потом увидеть: "ой, а мой логин, телефон и почта уже заняты").
    Правда, по-хорошему в скрипте самой регистрации всё равно надо проверять все поля (1 или 2 методом, опять же).

    Добавлено спустя 46 секунд:
    ОФФТОП:
    когда? когда я пропустил свой 404-юбилей? :(
     
  3. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.114
    Симпатии:
    1.244
    Адрес:
    там-сям
    удали три своих сообщения и празднуй ;)

    Добавлено спустя 24 секунды:
    p.s. зачем здесь LIMIT 3?
     
  4. mr.akv

    mr.akv Активный пользователь

    С нами с:
    31 мар 2015
    Сообщения:
    1.604
    Симпатии:
    206
    логин, эмейл и телефон теоретически же могут быть в разных записях. А повторений каждого быть не должно, поэтому 3. :)
     
  5. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.114
    Симпатии:
    1.244
    Адрес:
    там-сям
    и как из этого следует, что нужен LIMIT ?
     
  6. mr.akv

    mr.akv Активный пользователь

    С нами с:
    31 мар 2015
    Сообщения:
    1.604
    Симпатии:
    206
    ну если лимит 3 стоит, то, найдя третий результат, он не пойдёт дальше по базе искать ведь. Меньше время работы, чтоль. Или я не так понимаю?)
     
  7. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.114
    Симпатии:
    1.244
    Адрес:
    там-сям
    ТОЧНО — ТЫ НЕ ТАК ПОНИМАЕШЬ.

    тебе вообще не надо добывать сами записи как SELECT *, а достаточно SELECT COUNT(*) или даже SELECT 1
    и тогда if (mysqli_num_rows($result)) сработает как проверка "такие записи уже существуют". ведь тебе не нужны ни сами значения, ни даже знание сколько их там. важен только факт — они есть или их нет.

    Voila!

    Ну если очень хочется, то можно поставить LIMIT 1

    Добавлено спустя 51 минуту 6 секунд:
    update: что действительно важно, так это наличие индексов, гарантирующих непротиворечивость данных. если важно чтобы login или email встречались не более одного раза, делайте UNIQUE KEY. тогда даже ошибка в скрипте не приведет к появлению фиговой записи.

    следствие: когда есть уникальны индекс, вот в таких конструкциях …WHERE login = '$login' LIMIT 1 тоже нет необходимости. т.к. полюбому вернется не более одной записи.
     
  8. anvyd

    anvyd Новичок

    С нами с:
    17 апр 2015
    Сообщения:
    13
    Симпатии:
    0
    Спасибо за все ответы, советы.
    Особенно про уникальные индексы, об этом я не подумал, когда проектировал структуру БД, на будущее буду иметь ввиду
     
  9. mr.akv

    mr.akv Активный пользователь

    С нами с:
    31 мар 2015
    Сообщения:
    1.604
    Симпатии:
    206
    artoodetoo, хорошо, погуглю, почитаю.
    А вывод трёх полей данными вместо каунта я предполагал в расчёте на то, что в скрипте надо будет проверять, что именно совпало и выводить пользователю. До более мудрой мысли я не дошёл.
    P.S.: друг, я мелким шрифтом хорошо понимаю :D
     
  10. Chushkin

    Chushkin Активный пользователь

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    1. Плохое решение, - лучше с JOIN.
    2. Самый неправильный совет. Почитайте про JOIN.
    3. Неправильный совет - не решает задачу.

    Самое правильное решение предложил artoodetoo - уник.инддексы. Оно и самое простое может быть, - достаточно "Insert ignore..." + "->affected_rows".
     
  11. mr.akv

    mr.akv Активный пользователь

    С нами с:
    31 мар 2015
    Сообщения:
    1.604
    Симпатии:
    206
    Вот, благодаря автору и я учусь. Я ж не ставлю из себя зазнайку. Зато теперь сам знаю, что так неправильно. Хорошо же.
     
  12. anvyd

    anvyd Новичок

    С нами с:
    17 апр 2015
    Сообщения:
    13
    Симпатии:
    0
    Ребят, я конечно, извиняюсь, но я не совсем понял, я всё же хочу вникнуть, поэтому спрошу сразу
    Я устанавливаю уникальные ключи полям login, phone, email
    Я понимаю, что в БД не добавится запись, если пользователь введет значение, которое уже есть в таблице.
    Но мне ведь всё равно необходимо делать проверку, я же не могу сразу делать INSERT, а потом уже смотреть, добавились ли значения или нет, поэтому мне необходимо проверить, нет ли таких данных уже в таблице

    Соответственно я всё же делаю проверку типа
    Код (PHP):
    1. SELECT 1 FROM users WHERE login = '$login' OR email = '$email' OR phone = '$phone'  
    (Я бы написал запрос с JOIN, но я пока не могу, как только я пойму что к чему тут, я сделаю с помощью JOIN)

    Смотрю, если пришла "1", соответственно ЧТО-ТО из поступившей информации совпадает, а как же мне пользователю сообщить, что что-то в системе уже зарегистрировано, если я этим запросом по сути никаких конкретных данных не получаю? Я получаю лишь факт совпадения.
    Еще раз прошу прощения, может я слишком глуп и не понимаю очевидных вещей, но не хочу оставлять этот момент недопонятым

    п.с. Как я это вижу все таки:
    если первый запрос дает мне всё же единицу, мне необходимо делать еще один запрос
    типа
    Код (PHP):
    1. SELECT login, phone, email  FROM users WHERE login = '$login' OR email = '$email' OR phone = '$phone'  
    Я достаю login, phone, email, а потом сравниваю с полученными значениями и уведомляю пользователя о КОНКРЕТНОЙ ошибке, поправьте пожалуйста где я ошибаюсь
    Но зачем мне делать два запроса?
     
  13. mahmuzar

    mahmuzar Старожил

    С нами с:
    6 апр 2012
    Сообщения:
    4.631
    Симпатии:
    425
    Адрес:
    РД, г. Махачкала.
    Если данных в базе нету, то следующий запрос это уже INSERT не?
     
  14. p@R@dox 55RU

    p@R@dox 55RU Зэк
    [ БАН ]

    С нами с:
    21 май 2014
    Сообщения:
    1.358
    Симпатии:
    7
    Адрес:
    с планеты Ялмез
    автор, ты всё не правильно понял по поводу уникальных ключей ;)
     
  15. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.114
    Симпатии:
    1.244
    Адрес:
    там-сям
    мне кажется или ты хочешь обсудить вопрос "почему мне не хочется этого делать?". да хз почему! наверное потому что гемор с реальным проектом тебе не знаком и ты преувеличиваешь значимость каких-то деталей.

    изначально ты спрашивал как одним запросом понять не присутствуют ли в уже таблице уникальные по своей природе регистрационные данные — ты получил ответ.
     
  16. mr.akv

    mr.akv Активный пользователь

    С нами с:
    31 мар 2015
    Сообщения:
    1.604
    Симпатии:
    206
    зачем тебе два запроса? Этого одного не хватит?
    1. Достал эти данные
    2. Если результат пустой - делаешь инсерт
    3. если результат не пустой - смотришь какое поле конкретно (а их может быть и несколько, и даже все) совпало и выдаёшь пользователю ошибку. Я ж выше про это писал