10

我尝试像这样使用变量绑定:

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

但有些 $_POST['...'] 可能是空的,所以我不想在数据库中更新它们。

考虑空 $_POST['...'] 的所有不同组合是不切实际的,尽管我可以根据需要构建字符串“UPDATE mytable SET...”,但 bind_param() 是另一种野兽。

我可以尝试将其调用构建为字符串并在其上使用 eval() 但感觉不对:(

4

5 回答 5

25

您可以使用该call_user_func_array函数调用bind_param带有变量编号或参数的方法:

$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);
}
于 2009-04-27T13:41:14.510 回答
4

这就是我用可变数量的参数来做 mysqli 准备语句的方法。这是我写的课程的一部分。对于您需要的东西来说,它可能是矫枉过正,但它应该向您展示正确的方向。

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

你像这样使用它:

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

该类应扩展 mysqli_stmt 类。

我希望这可以帮助您朝着正确的方向前进。
如果你不想,我也可以发布整个课程,它包括变量结果绑定。

于 2009-04-27T13:38:12.440 回答
1

使用数组构建语句稍微清晰一些:

$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);
于 2009-04-27T13:37:01.307 回答
-1

array_insert 不存在,我猜他指的是一些自制的函数,但我不确定它到底做了什么......在开头的某个地方将参数类型插入到数组中我猜想是因为传递了值 0但嘿,它也可能最终出现;)

于 2013-06-19T13:02:26.587 回答
-2

将其构建为字符串,但将您的值放入数组并将其传递给 bindd_param。(并用 ? 代替 SQL 字符串中的值。

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

例如:

$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);
于 2009-04-27T13:28:26.053 回答