2008-10-14 16 views
7

Ich mag die Flexibilität von Dynamic SQL und ich mag die Sicherheit + verbesserte Leistung von vorbereiteten Anweisungen. Also, was ich wirklich will, ist Dynamic Prepared Statements, was mühsam zu machen ist, da bind_param und bind_result "feste" Anzahl von Argumenten akzeptieren. Also habe ich eine eval() Anweisung verwendet, um dieses Problem zu umgehen. Aber ich habe das Gefühl, dass das eine schlechte Idee ist. Hier ist ein Beispielcode dessen, was ich meineSind dynamische vorbereitete Anweisungen schlecht? (mit php + mysqli)

// 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); 

Ist das letzte Eval() Aussage eine schlechte Idee? Ich habe versucht, die Code-Injektion zu vermeiden, indem ich Werte hinter dem Variablennamen $ param kapselt.

Hat jemand eine Meinung oder andere Vorschläge? Gibt es Probleme, auf die ich achten muss?

+0

Vielleicht möchten Sie Ihre Frage umformulieren Titel ein wenig, damit andere Ihre Frage leichter finden können. – Tomalak

Antwort

13

Ich denke, es ist gefährlich, eval() hier zu verwenden.

Try this:

  • iterieren die params Array die SQL-Zeichenfolge mit Fragezeichen "SELECT * FROM t1 WHERE p1 = ? AND p2 = ?"
  • Aufruf zu bauen prepare() auf dieser
  • Verwendung call_user_func_array() den Anruf zu bind_param() zu machen, in dem dynamischen params vorbei Array.

Der Code:

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

Seien Sie vorsichtig mit 'array ($ types) + $ param'. Wenn $ param ein Array mit einem Index von 0 ist, dann wird dieser Wert in $ param zugunsten von $ types fallengelassen, und Sie erhalten einen Fehler, wenn Sie weniger Variablen haben als in Ihrer Zeichenkette angegeben. http://php.net/manual/en/language.operators.array.php – Tushar

-1

Sie nicht wirklich brauchen, Prepared Statements und gebundene Argumente, weil man immer mysql_real_escape_string() verwenden. Und du hast recht; dynamisch generiertes SQL ist viel flexibler und wertvoller.

Hier ist ein einfaches Beispiel der regelmäßige mysql_ * Schnittstelle:

// 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); 

Natürlich ist dies ein einfaches Beispiel, und macht es sinnvoll, müssen Sie bauen und es viel zu verfeinern, aber es zeigt die Ideen und es ist wirklich sehr, sehr nützlich. Zum Beispiel ist hier eine völlig generische Funktion eine neue Zeile in eine beliebige Tabelle einzufügen, wobei die Spalten mit den Werten aus einem assoziativen Array gefüllt und vollständig SQL-Injektion sicher:

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)); 
+2

Gebundene Parameter bietet zusätzliche Sicherheit über die Flucht hinaus. Es ist eine gute Übung, sie zu benutzen. – troelskn

+1

Könnten Sie mir bitte zeigen, welche zusätzliche Sicherheit sie dann anbieten? Vor welcher Art von Angriff würden Sie mit gebundenen Parametern gegen meine Lösung geschützt werden? Wenn Sie sich auf die Fähigkeit eines Programmierers beziehen, Fehler zu machen, hätte ich lieber die leistungsfähigeren Werkzeuge als die einschränkenden Werkzeuge. – rix0rrr

+0

+1 Danke Mann! Das ist eine gute Lösung! – RubyDubee