2016-11-28 2 views
2

Это далеко не идеальный вариант, но я пытаюсь создать функцию для вставки данных в таблицу SQL с использованием MySQLI. Я хочу создать общую функцию, чтобы вставлять различные типы данных в разные базы данных. У меня есть следующее:Вставить массив неопределенной длины в MYSQLI

/** 
* Add data to specified table. Data consist of column name as key, and value. 
* Table is a string of the table to insert into. 
* @param array $data 
* @param string $table 
* @return string 
*/ 
private function insert($data = array(), $table = null){ 

    foreach($data as $key => $value){ 

     // Create arrays of separate keys and values 
     $keys[]  = $key; 
     $values[] = $value; 

     // Get type of data 
     switch(gettype($value)){ 
      case "integer": 
       $types[] = "i"; 
       break; 
      case "string": 
       $types[] = "s"; 
       break; 
      default: 
       $types[] = "i"; 
       break; 
     }; 

     // for each variable, add a questionmark 
     $vars[]  = "?"; 

    } 

    // Create strings out of the data 
    $key = implode(",", $keys); 
    $var = implode(",", $vars); 
    $type = implode("", $types); 
    $value = '"' . implode('\", \"', $values) . '"'; 

    // prepare SQL statement 
    // var_dump($sql) = 'INSERT INTO table (var1,var2,var3) VALUES (?,?,?)' 
    $sql = "INSERT INTO " . $table . " (" . $key . ") VALUES (" . $var . ")"; 

    // Prepare SQL insert 
    // $this->conn = new mysqli($this->server, $this->user, $this->pass, $this->name); 
    if(! ($stmt = $this->conn->prepare($sql))) { 
     return "Preparing failed!: (" . $this->conn->errno . ") " . $this->conn->error; 
    } 

    // Bind parameters. THIS IS WHERE THE ISSUE IS! 
    if(! $stmt->bind_param($type, $values)) { 
     return "Binding failed! (" . $stmt->errno . ") " . $stmt->error;; 
    } 

    // Execute the statement 
    if(! $stmt->execute()){ 
     return "Executing failed! (" . $stmt->errno . ") " . $stmt->error;; 
    } 

} 

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

Короче говоря, m ищет способ добавить массив неуказанной длины в мой SQL (безопасным способом, конечно).

+0

FYI, этот код уязвим для SQL-инъекции. –

+0

Спасибо, я все еще должен заглянуть в это. Я знаю об этом, хотя я еще не уделял этому времени. Вероятно, лучше это делать во время написания, но я все еще работаю над этим. Спасибо за головы, хотя! –

ответ

3

Если вы используете PHP 5.6+, вы можете использовать оператор ... распаковать массив.

В вашем примере:

$stmt->bind_param($type, ...$values) 

См пример # 14 в manual.

+1

Ничего себе, если бы я знал, что это было так просто! Это замечательный материал. Благодарю. Я соглашусь, когда смогу (если не произойдет что-то лучше, конечно) –

+1

Это '...' звонит в дальний звонок, и я не могу вспомнить ... о, подождите, я просто вспомнил (поскольку я печатал это, это вернулся ко мне); PERL/CGI. Я использовал этот точный синтаксис для того, над чем я работал много лет назад. Приятно видеть, что вы можете использовать это в PHP. Edit: Опять же, это может быть '..' * lol *, но это достаточно близко ;-) –

+0

@ Fred-ii- Должен признаться, я очень рад, что PERL/CGI - это не более чем очень далекая память многих лет назад ;-) – jeroen

1
/* Bind parameters. Types: s = string, i = integer, d = double, b = blob */ 
$a_params = array(); 

$param_type = ''; 
$n = count($a_param_type); 
for($i = 0; $i < $n; $i++) { 
    $param_type .= $a_param_type[$i]; 
} 

/* with call_user_func_array, array params must be passed by reference */ 
$a_params[] = & $param_type; 

for($i = 0; $i < $n; $i++) { 
    /* with call_user_func_array, array params must be passed by reference */ 
    $a_params[] = & $a_bind_params[$i]; 
} 

/* Prepare statement */ 
$stmt = $conn->prepare($sql); 
if($stmt === false) { 
    trigger_error('Wrong SQL: ' . $sql . ' Error: ' . $conn->errno . ' ' . $conn->error, E_USER_ERROR); 
} 

/* use call_user_func_array, as $stmt->bind_param('s', $param); does not accept params array */ 
call_user_func_array(array($stmt, 'bind_param'), $a_params); 

/* Execute statement */ 
$stmt->execute(); 

/* Fetch result to array */ 
$res = $stmt->get_result(); 
while($row = $res->fetch_array(MYSQLI_ASSOC)) { 
    array_push($a_data, $row); 
} 

Ссылка: http://www.pontikis.net/blog/dynamically-bind_param-array-mysqli

+0

Очень хорошее решение, но не так просто, как тот, который дается Jeroen. –