Можете ли вы интерполировать переменную в строку по ссылке? - PullRequest
1 голос
/ 29 марта 2020

Моя общая цель - привязать переменную к подготовленному выражению, но мне нужно сделать это по ссылке. Я знаю, что mysqli_stmt::bind_param уже связывает переменные по ссылке, но мне нужно, чтобы он работал с переменным числом переменных. Например:

$stmt = $conn->prepare("SELECT * FROM accounts WHERE id IN (?, ?, ?, ? /* unknown number of question marks */);");

Чтобы обойти это, я наткнулся на это решение (второй блок кода в принятом ответе): У меня есть массив целых чисел, как мне использовать каждое из них в mysql запрос (в php)?

В этом решении связанные значения $params интерполируются в запрос. Тем не менее, я не буду знать, какое количество параметров мне понадобится, до тех пор, пока не будет:

// I don't know yet how many values will be needed for the IN expression.

$stmt = $conn->prepare("SELECT * FROM ingredients WHERE id IN ($params);");

while ($doingSomething) {
    $ids = getTheIds();

    // Okay, now I know how many.

    $params = implode(",", array_fill(0, count($ids), "?")); // $params can finally be set

    $types = str_repeat("i", count($ids));                        // "iiii"
    $args = array_merge(array($types), $ids);                     // ["iiii", 2, 4, 6, 8]
    call_user_func_array(array($stmt, 'bind_param'), ref($args)); // $stmt->bind_param("iiii", 2, 4, 6, 8)

    $stmt->execute();
    // The statement fails because $params wasn't set when the query was prepared
}

Я мог бы поместить подготовку оператора в l oop, после того как узнал размер $ids, но это как бы побеждало цель его подготовки.

На мой взгляд, если бы $params в подготовленном запросе было передано по ссылке, это решило бы мою проблему. Возможно ли это, или, возможно, я неправильно смотрю на всю эту проблему?

1 Ответ

1 голос
/ 30 марта 2020

Вы не можете подготовить запрос, пока не будете точно знать, как будет выглядеть этот запрос. В вашем случае вы создаете SQL динамически в зависимости от необходимого количества заполнителей. Пока вы не знаете количество заполнителей, вы не можете подготовить запрос.

Вам необходимо сделать это внутри l oop.

while ($doingSomething) {
    $ids = getTheIds();

    // Okay, now I know how many.

    $params = implode(",", array_fill(0, count($ids), "?")); // $params can finally be set
    $stmt = $conn->prepare("SELECT * FROM ingredients WHERE id IN ($params);");

    $types = str_repeat("i", count($ids));  // "iiii"
    $stmt->bind_param($types, ...$ids);

    $stmt->execute();
}

. Примечание:

  1. Рекомендую перейти на PDO, если такой все намного проще. Если вы начинаете новый проект, не используйте класс mysqli.
  2. Пожалуйста, убедитесь, что для mysqli включена поддержка отчетов об ошибках. См. Как получить сообщение об ошибке в MySQLi?
  3. Не использовать функцию call_user_func_array при вызове bind_param. Вы только делаете это более сложным, чем нужно.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...