2014-01-05 1 views
2

Это мой код:Как использовать php-массив в подготовленном заявлении для оператора SQL IN с помощью SQLi?

if(isset($_POST['abc'])) 
{ 
    $things['abc'] = mysqli_real_escape_string($connect, implode("','", $_POST['abc'])); 

    $result = mysqli_query($connect, "SELECT * FROM this_list WHERE abc_column IN ('{$things['abc']}')"); 

    if (!$result) 
    {  
     echo "Error fetching results: " . mysqli_error(); 

    } 
    else 
    { 
     while ($row = mysqli_fetch_array($result)) 
     { 
      $abc[] = $row['description']; 
     } 
    } 
} 

Приведенный выше код использует mysqli_real_escape_string(), а $things представляет собой массив со значениями флажок, который принимается через POST. Этот массив содержит список строк, разделенных запятой, которую я использую в запросе.

Когда я искал в сети, я заметил, что некоторые люди говорят, что mysqli_real_escape_string() может помешать внедрению sql, я думал, что готовый оператор для значений флажка может быть более безопасным для SQL-инъекции.

Я использовал подготовленную инструкцию с отдельными параметрами для предотвращения внедрения sql. Но я застрял в этом, и я не знаю, как изменить приведенный выше код на инструкцию prepare(), поскольку он использует массив $things['abc']. Я пробовал поиск и каждый раз, когда я искал массив в подготовленном сообщении, я получаю информацию о Java и т. Д. Может кто-нибудь просветить меня о том, как я могу это сделать с помощью php, пожалуйста?

EDIT:

После помощи onetrickpony кода ниже, это то, что я сейчас:

if(isset($_POST['abc'])) 
    { 
     $ph = rtrim(str_repeat('?,', count($_POST['abc'])), ','); 
     $query = sprintf("SELECT col1 FROM abc_table WHERE col2 IN (%s)", $ph); 

     $stmt = mysqli_prepare($connect, $query); 

     // bind variables 
     $params = array(); 
     foreach($_POST['abc'] as $v) 
      $params[] = &$v; 

     array_unshift($params, $stmt, str_repeat('s', count($_POST['abc']))); // s = string type 
     call_user_func_array('mysqli_stmt_bind_param', $params); 

     mysqli_stmt_execute($stmt); 

     // Get the data result from the query. 
     mysqli_stmt_bind_result($stmt, $col1); 

     /* fetch values and store them to each variables */ 
     while (mysqli_stmt_fetch($stmt)) { 
      $name[] = $col1; 
      echo $name;   
     } 

     //loop to echo and see whats stored in the array above 
     foreach($name as $v) { 
       echo $v; 
     } 


     // Close the prepared statement. 
     $stmt->close(); 

    } 

В приведенном выше коде, SQLI способ подготовить заявление, кажется, работает, который Великий. Однако, когда я использую mysqli_stmt_bind_result(), массив $ name [] внутри цикла while, похоже, печатает последнюю строку.

UPDATE: Код

onetrickpony с Mysqli в методе с использованием массива PHP в заявлении работал хорошо, и это был очень хороший подход, он предложил. Тем не менее, у меня был кошмар со второй половиной кода, который пытается заставить результаты извлеченного массива работать. Пробыв больше дня, я отказался от этого, и я переключил на PDO. Снова пособие onetrickpony было полностью оправдано. Переход на PDO сделал код намного проще и проще и не мог поверить.

+1

[* PHP PDO: Могу ли я привязать массив к условию IN() *) (http: // stackoverflow .com/questions/920353/php-pdo-can-i-bind-an-array-to-an-in-condition) –

+0

спасибо за ссылку. Есть ли для него метод SQLi? Я не использовал PDO, и все мои скрипты atm используют метод sqli. – Neel

ответ

2

Попробуйте это:

// build placeholder string (?,?...) 
$ph = rtrim(str_repeat('?,', count($_POST['abc'])), ','); 
$query = sprintf("SELECT * FROM this_list WHERE abc_column IN (%s)", $ph); 

$stm = mysqli_prepare($connect, $query); 

// bind variables (see my notes below) 
$params = array(); 
foreach($_POST['abc'] as $v) 
    $params[] = &$v; 

             // s = string type 
array_unshift($params, $stm, str_repeat('s', count($_POST['abc']))); 
call_user_func_array('mysqli_stmt_bind_param', $params); 

mysqli_stmt_execute($stm); 

Оказывается, что mysqli_stmt_bind_param нельзя назвать несколько раз, чтобы связать несколько переменных. И что еще хуже, для этого требуются ссылочные переменные. Я бы рекомендовал вам переключиться на PDO, только из-за этих ограничений, которые заставляют вас писать уродливый код :)

+0

Мне нравится ваш подход. Но когда я пытаюсь это сделать, я получаю сообщение об ошибке 'mysqli_stmt_bind_param() [function.mysqli-stmt-bind-param]: Число переменных не соответствует количеству параметров в подготовленном сообщении' – Neel

+0

Теперь он должен работать. Я переоценил 'mysqli_stmt_bind_param' :) –

+0

Извините .. обновил код, но он показывает эту ошибку' mysqli_stmt_bind_param() ожидает, что параметр 1 будет mysqli_stmt, строка задана'. Эта ошибка относится к этой строке: 'call_user_func_array ('mysqli_stmt_bind_param', $ params);' – Neel

Смежные вопросы