Являются ли динамические подготовленные заявления плохими? (с php + mysqli)

Мне нравится гибкость Dynamic SQL, и мне нравится безопасность + улучшенная производительность подготовленных заявлений. Так что я действительно хочу, это динамические подготовленные заявления, что сложно сделать, потому что bind_param и bind_result принимают «фиксированное» количество аргументов. Поэтому я использовал инструкцию eval (), чтобы обойти эту проблему. Но я чувствую, что это плохая идея. Вот пример кода, что я имею в виду

// array of WHERE conditions $param = array('customer_id'=>1, 'qty'=>'2'); $stmt = $mysqli->stmt_init(); $types = ''; $bindParam = array(); $where = ''; $count = 0; // build the dynamic sql and param bind conditions foreach($param as $key=>$val) { $types .= 'i'; $bindParam[] = '$p'.$count.'=$param["'.$key.'"]'; $where .= "$key = ? AND "; $count++; } // prepare the query -- SELECT * FROM t1 WHERE customer_id = ? AND qty = ? $sql = "SELECT * FROM t1 WHERE ".substr($where, 0, strlen($where)-4); $stmt->prepare($sql); // assemble the bind_param command $command = '$stmt->bind_param($types, '.implode(', ', $bindParam).');'; // evaluate the command -- $stmt->bind_param($types,$p0=$param["customer_id"],$p1=$param["qty"]); eval($command); 

Это последнее утверждение eval () – плохая идея? Я пытался избежать инъекции кода, инкапсулируя значения за именем переменной $ param.

Кто-нибудь имеет мнение или другие предложения? Есть ли проблемы, о которых я должен знать?

Я думаю, что использовать eval() здесь опасно.

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

  • итерации массива params для построения строки SQL с вопросительными знаками "SELECT * FROM t1 WHERE p1 = ? AND p2 = ?"
  • call prepare() к этому
  • используйте call_user_func_array() чтобы сделать вызов bind_param() , передав массив динамических параметров.

Код:

 call_user_func_array(array($stmt, 'bind_param'), array($types)+$param); 

Вам действительно не нужны подготовленные операторы и связанные аргументы, потому что вы всегда можете использовать mysql_real_escape_string (). И ты прав; динамически созданный SQL гораздо более гибкий и ценный.

Вот простой пример использования обычного интерфейса mysql_ *:

 // Array of WHERE conditions $conds = array("customer_id" => 1, "qty" => 2); $wherec = array("1"); foreach ($conds as $col=>$val) $wherec[] = sprintf("`%s` = '%s'", $col, mysql_real_escape_string($val)); $result_set = mysql_query("SELECT * FROM t1 WHERE " . implode(" AND ", $wherec); 

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

 function insert($table, $record) { $cols = array(); $vals = array(); foreach (array_keys($record) as $col) $cols[] = sprintf("`%s`", $col); foreach (array_values($record) as $val) $vals[] = sprintf("'%s'", mysql_real_escape_string($val)); mysql_query(sprintf("INSERT INTO `%s`(%s) VALUES(%s)", $table, implode(", ", $cols), implode(", ", $vals))); } // Use as follows: insert("customer", array("customer_id" => 15, "qty" => 86));