SQL — выберите имя пользователя, ГДЕ роль = $string

У меня есть таблица, в которой хранятся пользователи и их роли. Пользователи могут иметь 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 вручную, все работает нормально.

Вы действительно храните список, разделенный запятыми, в столбце role?

Barmar 04.03.2019 23:28

А на входе тоже может быть несколько ролей? Вы хотите найти пользователей, у которых есть все эти роли, или пользователей, у которых есть какая-либо из них?

Barmar 04.03.2019 23:29

Я не строил БД. я просто должен работать над этим. столбец роли выглядит следующим образом: роль varchar (250)

LotusPrime 04.03.2019 23:32

Если у пользователя есть какая-либо из ролей из выбранных ролей, она должна быть извлечена из базы данных.

LotusPrime 04.03.2019 23:33

Пробелы после запятых — настоящая проблема, они мешают работе FIND_IN_SET().

Barmar 04.03.2019 23:33
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
5
89
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вам нужно разделить ввод на массив ролей. Затем вам нужно использовать 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); . Прямо сейчас он ничего не возвращает, и, возможно, я что-то упускаю

LotusPrime 05.03.2019 00:02

Эхо этого запроса: ВЫБЕРИТЕ имя пользователя ОТ пользователей, ГДЕ НАЙТИ_IN_SET('Финанса', ЗАМЕНИТЬ(роль, ', ', ',')) ИЛИ НАЙТИ_IN_SET('ЭТО', ЗАМЕНИТЬ(роль, ', ', ','))

LotusPrime 05.03.2019 00:10

Замените $db на фактическую переменную подключения к базе данных.

Barmar 05.03.2019 00:12

сделал это. мой $ссылка

LotusPrime 05.03.2019 00:15

Вы изменили его в обоих местах, use($link) и $link->real_escape_string?

Barmar 05.03.2019 00:19

Это необходимо для защиты от SQL-инъекций путем экранирования ввода. Если вы используете PDO, проще создать подготовленный оператор с динамическим количеством параметров.

Barmar 05.03.2019 00:20

Я удалил пробелы после , . Должен ли я что-либо изменить здесь return "FIND_IN_SET('$role', REPLACE(role, ', ', ','))"; Отредактировал так: "FIND_IN_SET('$role', REPLACE(role, ',', ','))"; Все еще не работает, ничего не возвращает

LotusPrime 05.03.2019 00:33

Хорошо. Это была моя ошибка, когда я добавил еще один «там, где он не был нужен». Ваш код теперь работает как шарм. Спасибо

LotusPrime 05.03.2019 00:42

Вам не нужно вызывать REPLACE(), если пробелы уже удалены, просто используйте role там.

Barmar 05.03.2019 03:45

Я попытался получить список пользователей, которых я извлекаю из базы данных, и поместить их в раскрывающийся список, но список оказывается пустым. Полный код см. в приведенном выше коде.

LotusPrime 05.03.2019 17:10

Если var_dump($row['username']) показывает имя пользователя, я не понимаю, как раскрывающийся список может быть пустым. Видите ли вы варианты, если используете View Source? Это может быть просто потому, что вы создаете недопустимый HTML, смешивая вывод отладки с <option> внутри <select>

Barmar 05.03.2019 17:33

Показан только вариант <option value = "">Empty</option>. Я также попытался повторить всю страницу, используя require_once, и отображается раскрывающийся список с данными, извлеченными из базы данных. На данный момент я даже не понимаю этого больше

LotusPrime 05.03.2019 18:24

Я не понимаю, как это возможно. Это напечатано веткой else, но вы сказали, что получаете вывод из ветки var_dump($row['username']), которая находится в ветке if.

Barmar 05.03.2019 18:28

Вы уверены, что этот код запускается только тогда, когда пользователь отправляет форму с полем ввода «Роли»?

Barmar 05.03.2019 18:29

да, коды запускаются только после того, как пользователь отправил форму. Также код отлично работает, если я пытаюсь найти роль вручную: WHERE role = 'Financa'

LotusPrime 05.03.2019 18:55

Выполняется либо блок if, либо блок else, они не могут одновременно выполняться одновременно. var_dump есть только в блоке if, а Empty только в блоке else. Вы не можете получить оба результата, но это то, что вы говорите.

Barmar 05.03.2019 18:58

Должно быть что-то еще, выполняющее код дважды с разными входными данными.

Barmar 05.03.2019 18:59

К сожалению, код выполняется только один раз. Также, как я уже говорил, код работает нормально, если я пытаюсь найти роль вручную. Не хочу быть грубым, но вы уверены, что метод, который вы мне дали, правильный, в контексте скобок или «может быть, это портит код?»

LotusPrime 05.03.2019 19:27

Я начал с $_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)

Barmar 05.03.2019 19:32
SELECT username FROM users WHERE FIND_IN_SET('Financa', role)
LotusPrime 05.03.2019 19:34

Это выглядит правильно, я не могу объяснить, почему это не работает.

Barmar 05.03.2019 19:35

Другие вопросы по теме