2009-04-27 7 views
6

Ich versuche Variable zu verwenden, wie diese Bindung:Verwenden Sie eine bind_param() mit variabler Anzahl von Eingangs Vars

$stmt = $mysqli->prepare("UPDATE mytable SET myvar1=?, myvar2=... WHERE id = ?")) { 
$stmt->bind_param("ss...", $_POST['myvar1'], $_POST['myvar2']...); 

aber einige der $ _POST [‘... '] leer sein könnte, so I don' Ich möchte sie in der DB aktualisieren.

Es ist nicht praktisch, die verschiedenen Kombinationen von leeren $ _POST ['...'] zu berücksichtigen, und obwohl ich die Zeichenfolge "UPDATE mytable SET ..." auf meine Bedürfnisse aufbauen kann, ist bind_param() ein anderes Tier.

Ich könnte versuchen, seinen Ruf als String und Verwendung eval Gebäude() auf, aber es fühlt sich nicht richtig :(

Antwort

-2

es als String bauen, aber Ihre Werte in ein Array gesetzt und übergeben, das zu bindd_param (und ersetzen? s für Werte in Ihrer SQL-Zeichenfolge.

$ stmt = $ mysqli-> vorbereiten ("UPDATE MYTABLE SET myvar1 = ?, myvar2 = ... WHERE ID =?")) { $ stmt-> bind_param ("ss ...", $ _POST [ 'MyVar1'], $ _POST [ 'MyVar2'] ...);

Zum Beispiel:

+1

@altCongnito tut 'array_insert() 'existiert tatsächlich? –

+0

Sie haben '$ sql + =' anstelle von '$ sql. =' – pmrotule

1

Es ist geringfügig mehr klar Ihre Anweisung ein Array zu erstellen:

$params = array(); 
$fragments = array(); 
foreach($_POST as $col => $val) 
{ 
    $fragments[] = "{$col} = ?"; 
    $params[] = $val; 
} 

$sql = sprintf("UPDATE sometable SET %s", implode(", ", $fragments)); 
$stmt = $mysqli->prepare($sql); 
$stmt->bind_param($params); 
+0

+1 für die Verwendung des Arrays geschrieben – cgp

+0

Ist es sicher, dass der Benutzer die Felder angibt, die so aktualisiert werden sollen? Ich denke nur, wenn das eine Benutzertabelle wäre und der Benutzer irgendwie herausfände, dass es eine Spalte gibt, in der seine Benutzerprivilegien gespeichert sind, könnten sie einfach ihre Benutzerprivilegien eskalieren, indem sie einen Formularbeitrag mit der richtigen Schlüssel/Wert-Kombination senden. – Calvin

+2

Unter keinen Umständen ist es gut, den Benutzer die Felder angeben zu lassen. Zumindest sollte er ein Array $ valid_fieldnames haben und überprüfen, ob (isset ($ valid_fieldnames [$ col])) als der Körper der foreach. (Ich bevorzuge Array ('Feld' => 1, 'Feld2' => 1, ...) über Array ('Feld', 'Feld2', ...) als isset() ist schneller als in_array().) – jmucchiello

3

Das ist, was ich zu tun verwenden Mysqli vorbereitete Anweisungen mit einer variablen Menge von params. Es ist Teil einer Klasse, die ich geschrieben habe. Es ist wahrscheinlich Overkill für das, was Sie brauchen, aber es sollte Ihnen die richtige Richtung zeigen.

public function __construct($con, $query){ 
    $this->con = $con; 
    $this->query = $query; 
    parent::__construct($con, $query); 
    //We check for errors: 
    if($this->con->error) throw new Exception($this->con->error); 
} 

protected static $allowed = array('d', 'i', 's', 'b'); //allowed types 

protected static function mysqliContentType($value) { 
    if(is_string($value)) $type = 's'; 
    elseif(is_float($value)) $type = 'd'; 
    elseif(is_int($value)) $type = 'i'; 
    else throw new Exception("type of '$value' is not string, int or float"); 
    return $type; 
} 

//This function checks if a given string is an allowed mysqli content type for prepared statement (s, d, b, or i) 
protected static function mysqliAllowedContentType($s){ 
    return in_array($s, self::$allowed); 
} 

public function feed($params){ 
    //These should all be empty in case this gets used multiple times 
    $this->paramArgs = array(); 
    $this->typestring = ''; 
    $this->params = $params; 
    $this->paramArgs[0] = ''; 
    $i = 0; 
    foreach($this->params as $value){ 
     //We check the type: 
     if(is_array($value)){ 
      $temp = array_keys($value); 
      $type = $temp[0]; 
      $this->params[$i] = $value[$type]; 
      if(!self::mysqliAllowedContentType($type)){ 
       $type = self::mysqliContentType($value[$type]); 
      } 
     } 
     else{ 
      $type = self::mysqliContentType($value); 
     } 
     $this->typestring .= $type; 
     //We build the array of values we pass to the bind_params function 
     //We add a refrence to the value of the array to the array we will pass to the call_user_func_array function. Thus say we have the following 
     //$this->params array: 
      //$this->params[0] = 'foo'; 
      //$this->params[1] = 4; 
     //$this->paramArgs will become: 
      //$this->paramArgs[0] = 'si'; //Typestring 
      //$this->paramArgs[1] = &$this->params[0]; 
      //$this->paramArgs[2] = &$this->params[1]. 
     //Thus using call_user_func_array will call $this->bind_param() (which is inherented from the mysqli_stmt class) like this: 
      //$this->bind_param('si', &$this->params[0], &$this->params[1]); 
     $this->paramArgs[] = &$this->params[$i]; 
     $i++; 
    } 
    unset($i); 
    $this->paramArgs[0] = $this->typestring; 
    return call_user_func_array(array(&$this, 'bind_param'), $this->paramArgs); 
} 

Sie verwenden es wie folgt aus:

$prep = new theClassAboveHere($mysqli, $query); 
$prep->feed(array('string', 1, array('b', 'BLOB DATA')); 

Die Klasse sollte die mysqli_stmt Klasse erweitern.

Ich hoffe, das hilft Ihnen in die richtige Richtung.
Wenn Sie möchten, könnte ich auch die gesamte Klasse buchen, es enthält variable Ergebnisse Bindung.

+1

Bitte poste die ganze Klasse. – svenkapudija

24

könnten Sie verwenden die Funktion call_user_func_array die bind_param Methode mit einer variablen Anzahl oder Argumenten zu nennen:

$paramNames = array('myvar1', 'myvar2', /* ... */); 
$params = array(); 
foreach ($paramNames as $name) { 
    if (isset($_POST[$name]) && $_POST[$name] != '') { 
     $params[$name] = $_POST[$name]; 
    } 
} 
if (count($params)) { 
    $query = 'UPDATE mytable SET '; 
    foreach ($params as $name => $val) { 
     $query .= $name.'=?,'; 
    } 
    $query = substr($query, 0, -1); 
    $query .= 'WHERE id = ?'; 
    $stmt = $mysqli->prepare($query); 
    $params = array_merge(array(str_repeat('s', count($params))), array_values($params)); 
    call_user_func_array(array(&$stmt, 'bind_param'), $params); 
} 
+1

Ich wollte nur erwähnen, dass in PHP 5.3+ der obige Code nicht funktioniert, da er Array-Werte als Referenz benötigt. Siehe: http://php.net/manual/de/mysqli-stmt.bind-param.php – Alex2php

+0

Verwenden Sie stattdessen 'bind_values'. – Gumbo

+0

Wo finde ich das in MYSQLi? Ich kenne es nur von PDO. – Alex2php

-1

array_insert existiert nicht, ich bin zu raten, er bis zu einem gewissen hausgemachten Funktion bezieht, aber ich bin nicht sicher, was genau es tut ... fügt die Parametertypen irgendwo am Anfang in das Array ein Ich würde raten, da der Wert 0 übergeben wird, aber hey, es könnte auch am Ende sein;)

+3

hmm ... sieht das eher wie ein Kommentar als eine Antwort aus? – kleopatra

Verwandte Themen