2009-04-27 18 views
6

tôi cố gắng sử dụng biến ràng buộc như thế này:Sử dụng một bind_param() với số biến của các đầu vào vars

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

nhưng một số $ _POST [' ... '] có thể có sản phẩm nào vì vậy tôi don' t muốn cập nhật chúng trong DB. Nó không phải là thực tế để đưa vào tài khoản tất cả các sự kết hợp khác nhau của trống $ _POST ['...'] và mặc dù tôi có thể xây dựng chuỗi "UPDATE mytable SET ..." theo nhu cầu của tôi, bind_param() là một con thú khác.

tôi có thể cố gắng xây dựng cuộc gọi của nó như là một chuỗi và sử dụng eval() vào nó nhưng nó không cảm thấy đúng :(

Trả lời

-2

Xây dựng nó như là một chuỗi, nhưng đặt giá trị của bạn vào một mảng và vượt qua đó để bindd_param (và thay thế?) cho các giá trị trong chuỗi SQL của bạn

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

Ví dụ:

$args = array(); 
$sql = "UPDATE sometable SET "; 
$sep = ""; 
$paramtypes = ""; 
foreach($_POST as $key => $val) { 
    $sql .= $sep.$key." = '?'"; 
    $paramtypes .= "s"; // you'll need to map these based on name 
    array_push($args, $val); 
    $sep = ","; 
} 
$sql .= " WHERE id = ?"; 
array_push($args, $id); 
array_insert($args, $paramtypes, 0); 

$stmt = $mysqli->prepare($sql); 
call_user_func_array(array(&$stmt, 'bindparams'), $array_of_params); 
$stmt->bind_param($args); 
+1

@altCongnito does 'array_insert() 'thực sự tồn tại? –

+0

Bạn đã viết '$ sql + =' thay vì '$ sql. =' – pmrotule

1

Nó là nhẹ rõ ràng hơn để xây dựng báo cáo của bạn sử dụng một mảng:

$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 để sử dụng mảng – cgp

+0

Có an toàn để cho phép người dùng chỉ định các trường sẽ được cập nhật như thế không? Tôi chỉ nghĩ, nếu đó là bảng người dùng và người dùng đã phát hiện ra có một cột lưu trữ đặc quyền người dùng của họ, họ có thể dễ dàng chuyển đặc quyền người dùng của họ bằng cách gửi bài đăng biểu mẫu với kết hợp khóa/giá trị chính xác. – Calvin

+2

Không có trường hợp nào tốt cho phép người dùng chỉ định các trường. Ở mức tối thiểu, anh ta nên có một mảng $ valid_fieldnames và kiểm tra if (isset ($ valid_fieldnames [$ col])) làm cơ thể của foreach. (Tôi thích Array ('field' => 1, 'field2' => 1, ...) trên Array ('field', 'field2', ...) như isset() nhanh hơn in_array().) – jmucchiello

3

Đây là những gì tôi sử dụng để làm mysqli chuẩn bị báo cáo với một số lượng biến của params. Đó là một phần của một lớp tôi đã viết. Nó có thể vượt trội cho những gì bạn cần nhưng nó sẽ cho bạn thấy đúng hướng.

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

Bạn sử dụng nó như thế này:

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

Lớp nên mở rộng các lớp mysqli_stmt.

Tôi hy vọng điều này sẽ giúp bạn đi đúng hướng.
Nếu bạn không thể đăng cả lớp, nó bao gồm các kết quả khác nhau.

+1

Vui lòng đăng cả lớp. – svenkapudija

24

Bạn có thể sử dụng call_user_func_array chức năng để gọi phương thức bind_param với một số biến hoặc đối số:

$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

Chỉ muốn đề cập rằng trong PHP 5.3+ mã trên sẽ không hoạt động, bởi vì nó đòi hỏi các giá trị mảng làm tham chiếu. Xem: http://php.net/manual/de/mysqli-stmt.bind-param.php – Alex2php

+0

Sau đó, sử dụng 'bind_values' để thay thế. – Gumbo

+0

Tôi tìm thông tin này ở đâu trong MYSQLi? Tôi chỉ biết điều đó từ PDO. – Alex2php

-1

array_insert không tồn tại, tôi đoán ông đề cập đến một số nhà làm chức năng, nhưng tôi không chắc chắn chính xác những gì nó làm ... chèn các loại tham số vào mảng một nơi nào đó trong đầu tôi sẽ đoán vì giá trị 0 được thông qua nhưng hey nó có thể được ở cuối quá;)

+3

hmm ... điều này trông giống như một bình luận hơn là một câu trả lời? – kleopatra

Các vấn đề liên quan