我有一个这样做的函数:
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);
}