7

動的 SQL の柔軟性が気に入っています。セキュリティとプリペアド ステートメントのパフォーマンスの向上が気に入っています。したがって、私が本当に必要としているのは Dynamic Prepared Statements です。これは、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 の後ろに値をカプセル化することで、コード インジェクションを回避しようとしました。

誰か意見や他の提案はありますか? 注意が必要な問題はありますか?

4

3 に答える 3

14

ここで使うのは危険だと思いeval()ます。

これを試して:

  • params 配列を反復して、疑問符付きの SQL 文字列を作成します"SELECT * FROM t1 WHERE p1 = ? AND p2 = ?"
  • prepare()それを呼びなさい
  • call_user_func_array()を呼び出してbind_param()動的な params 配列を渡すために使用します。

コード:

call_user_func_array(array($stmt, 'bind_param'), array($types)+$param);
于 2008-10-14T15:23:22.830 に答える
-1

いつでも 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));
于 2008-10-15T15:22:45.093 に答える