Как использовать implode () для вставки нескольких целых чисел в оператор IN, используя подготовленные операторы в PHP? - PullRequest
0 голосов
/ 10 июля 2020

Контекст

У меня есть система каналов, где пользователи могут следить за другими пользователями на моем сайте и видеть их опубликованный контент, например созданные ими цепочки. Чтобы выполнить sh это, я использую AJAX для отправки массива со всеми идентификаторами пользователей, за которыми следует пользователь, для запроса в операторе SQL (моя СУБД - MySQL). Затем в PHP я пытаюсь взять этот массив и поместить его в свой запрос SQL, используя оператор IN. В этой конкретной ситуации c пользователь следует за двумя другими людьми с идентификаторами 11 и 12. Поэтому, отправив эти данные в код PHP через AJAX, я могу использовать print_r($_POST['following']) и получить следующий результат:

Array ( [0] => 11 [1] => 12 )

Чтобы использовать это в моем SQL запросе, я использую следующий код:

if ($_SERVER['REQUEST_METHOD'] == 'POST') {

$q = "SELECT forums.forum_id, forums.forum_title, forums.message, 
forums.idUsers, forums.box_id, forums.date, 
forums.seen, users.uidUsers, profileimages.image 
FROM forums 
JOIN users 
JOIN profileimages 
ON forums.idUsers = users.idUsers 
AND profileimages.idUsers = users.idUsers 
WHERE forums.idUsers 
IN (?) //code in question
ORDER BY forums.forum_id DESC 
LIMIT 5 
OFFSET ?";
$stmt = mysqli_prepare($conn, $q);
mysqli_stmt_bind_param($stmt, 'ii', $followingArray, $offset);

$following = $_POST['following'];
$followingArray = implode(", ", $following); //code in question
$offset = $_POST['offset'];

mysqli_stmt_execute($stmt);

После выполнения запроса я получаю информацию и отправляю ее обратно на сервер. Когда я делаю это таким образом, возвращается пять строк:

[{idUsers: 11, forumId: 11, seen: "false", forumTitle: "sixth random thread",…},…]
0: {idUsers: 11, forumId: 11, seen: "false", forumTitle: "sixth random thread",…}
1: {idUsers: 11, forumId: 10, seen: "false", forumTitle: "fifth random thread",…}
2: {idUsers: 11, forumId: 9, seen: "false", forumTitle: "fourth random thread",…}
3: {idUsers: 11, forumId: 8, seen: "false", forumTitle: "third random thread",…}
4: {idUsers: 11, forumId: 7, seen: "false", forumTitle: "second random thread",…}

Это хорошо, за исключением того факта, что при этом учитываются ТОЛЬКО сообщения с идентификатором пользователя 11, а не одновременно 11 и 12. Если оператор IN включал сообщения пользователя с идентификатором 12, тогда результаты были бы другими. После прямого входа в базу данных и повторного запроса после ввода значений вручную, например:

SELECT forums.forum_id, forums.forum_title, forums.message, 
forums.idUsers, forums.box_id, forums.date, 
forums.seen, users.uidUsers, profileimages.image 
FROM forums 
JOIN users 
JOIN profileimages 
ON forums.idUsers = users.idUsers 
AND profileimages.idUsers = users.idUsers 
WHERE forums.idUsers IN ('11', '12') 
ORDER BY forums.forum_id DESC 
LIMIT 5 OFFSET 0

Вы обнаружите, что результирующие строки были другими; первым результатом было сообщение от пользователя с идентификатором 12.

[,…]
[{idUsers: "12", forumId: "12", seen: "false", forumTitle: "first new content here",…},…]
0: {idUsers: "12", forumId: "12", seen: "false", forumTitle: "first new content here",…}
1: {idUsers: "11", forumId: "11", seen: "false", forumTitle: "sixth random thread",…}
2: {idUsers: "11", forumId: "10", seen: "false", forumTitle: "fifth random thread",…}
3: {idUsers: "11", forumId: "9", seen: "false", forumTitle: "fourth random thread",…}
4: {idUsers: "11", forumId: "8", seen: "false", forumTitle: "third random thread",…}

Это наводит меня на мысль, что моя реализация implode() с подготовленным оператором неверна.

Вопрос

Есть ли что-то, что я должен изменить с помощью функции implode(), например, заключить кавычки вокруг каждого значения в массиве, чтобы заставить его работать с оператором IN в MySQL?

Вещи, которые я пробовал

Полагая, что моя функция implode() была неправильно отформатирована, я попытался изменить переменную $followingArray с $followingArray = implode("', '", $following); на $followingArray = "'" . implode("', '", $following) . "'";, который просто вернул 0 строк. Как отформатировать функцию implode() для работы при попытке вставить несколько значений в оператор SQL?

Ответы [ 2 ]

2 голосов
/ 10 июля 2020

Вам НИКОГДА не следует связываться с кавычками, потому что это приводит к риску sql инъекции.

Более того, в этом конкретном примере вы вставляете числа, но в общем случае это не сработает. если вы хотите вставить строку типа «О'Коннор» и даже не говорить о том, хотите ли вы сохранить произвольный текст, содержащий как ', так и ": подготовленный оператор позаботится обо всем этом, о безопасности и спагетти с цитатами.

Мой совет - сначала count номер идентификатора, который вы будете запрашивать, и добавить это количество ? в предложение IN, например,

$idCount = //count ids
$questmarks = array_fill(0, $idCount, "?");
$sql .= "IN(".implode(",", $questmarks).")";

, если у вас есть скажем, 5 идентификаторов для запроса, подготовленная строка SQL будет выглядеть так:

SELECT ...
WHERE 
AND id IN (?,?,?,?,?)
LIMIT ?

, а затем свяжите все ваши параметры по порядку.

$params = [$id1,$id2,$id3,$id4,$id5,$offset];

mysqli_stmt_bind_param($stmt, "ii", ...$params);

0 голосов
/ 10 июля 2020

попробуйте это на основе ответа на этот вопрос { ссылка } $followingArray = "'" . implode("','", $following) . "'";

...