У меня есть таблица, в которой хранятся пользователи и их роли. Пользователи могут иметь 1 или более ролей. Роли хранятся в виде строки, где значения разделяются запятой после пробела.
//Get selected roles from user input on a string where values are separated by , and space
$roles = roleA, roleB; // --> user selected input
$query = "SELECT username FROM users WHERE role IN" .$roles;
$query = "SELECT username FROM users WHERE FIND_IN_SET(role, '$roles');
Полный код ниже:
<?php
include('dbConnect.php');
$roles = array_map('trim', explode(',',$_POST['role']));
$roles_tests = array_map(function($role) use ($link) {
$role = $link->real_escape_string($role);
return "FIND_IN_SET('$role', role)";
}, $roles);
$query = "SELECT username FROM users WHERE " . implode(' OR ', $roles_tests);
$results = mysqli_query($link, $query);
if (mysqli_num_rows($results) > 0) {
echo '<option value = "">Please choose</option>';
while($row = mysqli_fetch_array($results))
{
var_dump(mysqli_num_rows($results));
var_dump($row['username']);
echo '<option value = "'.$row['username'].'">'.$row['username'].'</option>';
}
}else{
echo '<option value = "">Empty</option>'; //display when no data!
}
?>
Результаты дампа Var:
var_dump(mysqli_num_rows($results)); --> 1
var_dump($row['username']); --> user1
Даже если он говорит, что num_rows = 1 все еще в цикле for, он получает его как 0, а раскрывающийся список пуст. Если я пытаюсь установить условия WHERE вручную, все работает нормально.
А на входе тоже может быть несколько ролей? Вы хотите найти пользователей, у которых есть все эти роли, или пользователей, у которых есть какая-либо из них?
Я не строил БД. я просто должен работать над этим. столбец роли выглядит следующим образом: роль varchar (250)
Если у пользователя есть какая-либо из ролей из выбранных ролей, она должна быть извлечена из базы данных.
Пробелы после запятых — настоящая проблема, они мешают работе FIND_IN_SET().






Вам нужно разделить ввод на массив ролей. Затем вам нужно использовать FIND_IN_SET(), чтобы проверить каждый из них в столбце role.
Вам также нужно удалить пробелы после запятых перед вызовом FIND_IN_SET(), так как он воспринимает их буквально.
Итак, запрос должен быть:
$roles = array_map('trim', explode(',', $_POST['role']));
$roles_tests = array_map(function($role) use ($db) {
$role = $db->real_escape_string($role);
return "FIND_IN_SET('$role', REPLACE(role, ', ', ','))";
}, $roles);
$query = "SELECT username FROM users WHERE " . implode(' OR ', $roles_tests);
Замените $db фактической переменной, которую вы используете для хранения объекта подключения к базе данных mysqli.
Можете ли вы объяснить, что это делает: $role = $db->real_escape_string($role); . Прямо сейчас он ничего не возвращает, и, возможно, я что-то упускаю
Эхо этого запроса: ВЫБЕРИТЕ имя пользователя ОТ пользователей, ГДЕ НАЙТИ_IN_SET('Финанса', ЗАМЕНИТЬ(роль, ', ', ',')) ИЛИ НАЙТИ_IN_SET('ЭТО', ЗАМЕНИТЬ(роль, ', ', ','))
Замените $db на фактическую переменную подключения к базе данных.
сделал это. мой $ссылка
Вы изменили его в обоих местах, use($link) и $link->real_escape_string?
Это необходимо для защиты от SQL-инъекций путем экранирования ввода. Если вы используете PDO, проще создать подготовленный оператор с динамическим количеством параметров.
Я удалил пробелы после , . Должен ли я что-либо изменить здесь return "FIND_IN_SET('$role', REPLACE(role, ', ', ','))"; Отредактировал так: "FIND_IN_SET('$role', REPLACE(role, ',', ','))"; Все еще не работает, ничего не возвращает
Хорошо. Это была моя ошибка, когда я добавил еще один «там, где он не был нужен». Ваш код теперь работает как шарм. Спасибо
Вам не нужно вызывать REPLACE(), если пробелы уже удалены, просто используйте role там.
Я попытался получить список пользователей, которых я извлекаю из базы данных, и поместить их в раскрывающийся список, но список оказывается пустым. Полный код см. в приведенном выше коде.
Если var_dump($row['username']) показывает имя пользователя, я не понимаю, как раскрывающийся список может быть пустым. Видите ли вы варианты, если используете View Source? Это может быть просто потому, что вы создаете недопустимый HTML, смешивая вывод отладки с <option> внутри <select>
Показан только вариант <option value = "">Empty</option>. Я также попытался повторить всю страницу, используя require_once, и отображается раскрывающийся список с данными, извлеченными из базы данных. На данный момент я даже не понимаю этого больше
Я не понимаю, как это возможно. Это напечатано веткой else, но вы сказали, что получаете вывод из ветки var_dump($row['username']), которая находится в ветке if.
Вы уверены, что этот код запускается только тогда, когда пользователь отправляет форму с полем ввода «Роли»?
да, коды запускаются только после того, как пользователь отправил форму. Также код отлично работает, если я пытаюсь найти роль вручную: WHERE role = 'Financa'
Выполняется либо блок if, либо блок else, они не могут одновременно выполняться одновременно. var_dump есть только в блоке if, а Empty только в блоке else. Вы не можете получить оба результата, но это то, что вы говорите.
Должно быть что-то еще, выполняющее код дважды с разными входными данными.
К сожалению, код выполняется только один раз. Также, как я уже говорил, код работает нормально, если я пытаюсь найти роль вручную. Не хочу быть грубым, но вы уверены, что метод, который вы мне дали, правильный, в контексте скобок или «может быть, это портит код?»
Я начал с $_POST['role'] == "role1,role2,role3", запрос был SELECT username FROM users WHERE FIND_IN_SET('role1', role) OR FIND_IN_SET('role2', role) OR FIND_IN_SET('role3', role)
SELECT username FROM users WHERE FIND_IN_SET('Financa', role)Это выглядит правильно, я не могу объяснить, почему это не работает.
Вы действительно храните список, разделенный запятыми, в столбце
role?