При запросе в БД выводится две строки, хотя должна только одна
public function searchLog() {
$searchlog = $_POST['searchlog'];
$login = strstr($searchlog, '_', true);
$search_login = trim(strstr($searchlog, '_'), '_');
$searchlog_sql = 'SELECT login FROM users';
$searchlog_result = mysqli_query($this->conn2, $searchlog_sql);
foreach ($searchlog_result as $row) {
if ($row['login'] == $search_login) {
echo $row['login'];
}
}
}
Cтолкнулся проблемой, foreach выдает два результата вместо одного, я перепробовал многие варианты, как быть?
Ответы (3 шт):
Начнём с того, что разрезать строку по разделителю можно гораздо проще:
[,$search_login] = explode('_',$searchlog);
Далее. Кто ж загребает всю базу данных, а потом перелопачивает её в скрипте? Если задача найти слово в бд, надо в запрос его и подставить:
$sql = "SELECT login FROM users WHERE login=?";
$result = $this->conn2->execute_query($sql, [$search_login]);
Разумеется, сразу с подстановками переменных.
Одним из важнейших умений программиста является адекватное восприятие реальности.
Если запрос к БД находит две строки, это значит, что в БД и лежит две строки, соответствующих этому запросу
В общем случае, если запрос выводит что-то не то, то надо сначала его и проверять:
- Сам запрос. В нём могут быть кривые или невыполнимые условия
- Используемые в запросе данные. Они могут быть перековерканы неумелыми ручками, или вообще отсутствовать.
- Данные в БД. Может быть, их там нету, или есть, но не те.
Соответственно, если из БД выводятся лишние строки, то надо не циклу foreach претензии предъявлять, а для начала проверить базу данных. То есть выполнить тот же самый запрос напрямую в БД, с помощью консоли, нормального GUI или дурацкой программы phpmyadmin (при этом надо помнить, у начинающих программистов бывает так, что РНР код коннкетится к одной БД, а дурацкая программа phpmyadmin - к другой).
И дальше разбираться со своей БД, удалять дублирующие записи, добавлять уникальный индекс, чтобы такое не повторялось в будущем. И только потом, убедившись, что строка осталась только одна, возвращаться к своему РНР коду.
Который, с одной стороны, не имеет отношения к вопросу, но уж слишком коряв, чтобы оставить его без внимания.
- если мы используем ООП, то никаких глобальных переменных, все данные извне передаются только явно в аргументах
- если мы используем ООП, то метод делает только что-то одно. Если это поиск по логину, то и выполнять он должен только поиск по логину, а не работу с протоколом HTTP и отрезание каких-то непонятных палочек
- если мы используем ООП, то пишем код, позволяющий его повторное использование. Поиск пользователя по логину нужен в куче мест, и поэтому надо написать поиск пользователя по логину, а потом использовать его в разных местах, в том числе и для проверки существования логина
- слово search подходит скорее для нечёткого поиска, по части логина, а у нас тут целый
- если мы ожидаем только один результат, то и цикла никакого не нужно, а надо сразу запросить у БД нужный результат, и получить его
В итоге получаем вот такую аккуратную функцию
public function getByLogin(string $login): ?array {
$sql = "SELECT login FROM users WHERE login=?";
$result = $this->conn2->execute_query($sql, [$login]);
return $result->fetch_assoc();
}
А уже при её вызове можно будет отрезать непонятные палочки и прочее. При этом надо помнить, никогда нельзя доверять входящим данным, в том числе что у них обязательно будет нужный формат
$parts = explode('_', $_POST['searchlog']);
$login = $parts[1] ?? null;
// если в $_POST['searchlog'] не было чёрточки
if ($login === null) {
// сделать что-то страшное
}
$user = $user->getByLogin($login);
if ($user) {
// нашли
} else {
// не нашли
}
Ну и вместо палочек рекомендую использовать универсальный формат JSON.
if (isset($_POST['searchlog'])) {
$fusions->searchLog();
}
В конце PHP скрипта случайно копировал этот кусочек дважды, поэтому он срабатывал дважды. Спасибо участникам за новые фишки в коде, буду использовать