将Param与参数数组绑定


Bind Param with array of parameters

我有一个这样做的函数:

function registerUser($firstName, $lastName, $address, $postcode, $email, $password)
{
    $params = array($firstName, $lastName, $address, $postcode, $email, $password);
    $result = $this->db->bind("INSERT INTO Users VALUES (?, ?, ?, ?, ?, ?)", 'ssssss', $params);
}

发送给我的数据库类,它做的是:

public function bind($query, $type, $params)
{
    $this->query = $query;
    $stmt = $this->mysqli->prepare($this->query);
    $stmt->bind_param($type, $param);
    $stmt->execute;
}

问题是这行不通。

我希望做的是采取$params列表,并让它在$type之后列出它们,以便查询类似:

$stmt->bind_param('ssssss', $firstName, $lastName, $address, $postcode, $email, $password);

但是很明显我用错了方法。

是否有办法使数组…转换为在bind_param查询阶段打印出来的列表?

call_user_func_array"使用参数数组调用回调"

call_user_func_array(array($stmt, "bind_param"), array_merge(array($type), $params));

应该做这项工作

UPDATE:你还必须改变你的参数数组:

$params = array(&$firstName, &$lastName, &$address, &$postcode, &$email, &$password);

作为mysqli_stmt::bind_param期望第二个和以下参数通过引用。


编辑:你的问题似乎是错误的。也许这里的字段比变量少。做的事:
"INSERT INTO Users (field1, field2, field3, field4, field5, field6) VALUES (?, ?, ?, ?, ?, ?)"

,用正确的名称替换字段的名称

从PHP 5.6开始,您可以使用参数解包作为call_user_func_array的替代方法,并且通常快3到4倍。

<?php
function foo ($a, $b) {
     return $a + $b;
}
$func = 'foo';
$values = array(1, 2);
call_user_func_array($func, $values);
//returns 3
$func(...$values);
//returns 3
?>

从这里取。

所以你的代码应该是这样的:
public function bind($query, $type, $params)
        {
            $this->query = $query;
            $stmt = $this->mysqli->prepare($this->query);
            $stmt->bind_param($type, ...$params);
            $stmt->execute;
        }

你得到你的错误"调用一个成员函数bind_param()在一个非对象上"最有可能,因为你的$this->mysqli->准备遇到某种错误。(参见http://php.net/manual/de/mysqli.prepare.php -它在错误时返回FALSE,这里似乎就是这种情况)

在你解决了这个问题之后,试试这个而不是调用$stmt->bind_param:

call_user_func_array(array($stmt, 'bind_param'), array_merge($type, $params));

最简单的方法显然是从mysqli切换到PDO

它可以让你按照你想要的方式去做,甚至不需要任何额外的函数:

function registerUser($firstName, $lastName, $address, $postcode, $email, $password)
{
    $sql  = "INSERT INTO Users VALUES (NULL, ?, ?, ?, ?, ?, ?)";
    $stmt = $this->db->prepare($sql);
    $stmt->execute(func_get_args());
}

需要注意的是,mysqli_stmt_bind_param()要求参数通过引用传递,因此call_user_func_array()的参数必须是引用。一个取自类上下文的例子:

function execute( string $query, string $type, array $params )
{
    if ( !$stmt = $this->mysqli->prepare( $query ) ) 
        throw new 'Exception( 'Prepare failed: ' . $query . PHP_EOL . $this->mysqli->error );
    // call stmt->bind_param() with variables to bind passed as a reference 
    call_user_func_array( 
        array( $stmt, 'bind_param' ), 
        array_merge( 
            array( $type ), 
            array_map( function( &$item ) { return $item; }, $params ) 
        ) 
    );
    if ( !$stmt->execute() ) 
        throw new 'Exception( 'Execute failed: ' . PHP_EOL . $stmt->error );
}
}

今天,为了创建一个使用prepare语句的更短的方法,我自己做了一些研究。答案@bwoebi是非常有用的,但不适用于未知数量的参数,所以这是他的答案的补充。

例如:

public function bind($query, $type, &...$params)
    {
        $this->query = $query;
        $stmt = $this->mysqli->prepare($this->query);
        call_user_func_array(array($stmt, "bind_param"), array_merge([$type], $params));
        $stmt->execute();
    }

使用这个线程:PHP:可变长度参数列表的引用?

我成功地将未知数量的参数传递给类中的bind函数。然后使用call_user_func_array(…)调用bind参数函数,并使用$type变量的数组合并…(必须放在数组内进行合并)

现在我可以调用这个函数,$email和$password现在是引用:

$myClass->bind($query, "ss", $email, $password);

不漂亮,但这就是我用的

function _BindParam(&$stmt, &$values){
    $types="";
    foreach($values as $val){
      if(is_string($val)){$types.="s";continue;}
      if(is_int($val)){$types.="i";continue;}
      if(is_float($val) || is_double($val)){$types.="d";continue;}
      throw new Exception('Invalid value type');
    }
   $stmt->bind_param($types,...$values);
}