FYI。最终使用PDO
解决方案,因为这更简单。
我正在尝试添加一个方法来处理对数据库的所有查询。我希望查询使用参数绑定。如何处理mysqli_stmt_bind_param()
中的可变数量的函数参数?
这篇文章here让我了解参数绑定的优点。
这是我的示例代码。我目前所处的位置是标记的。
输入参数
$query = "INSERT INTO b0 VALUES (?, ?, ?)"
$par_arr = {'bookmark', 'http://www.bookmark.com', 'tag'}
原型代码
protected static function query($query, $par_arr)
{
if($statement=mysqli_prepare(one::$db, $query)
{
mysqli_stmt_bind_param($statement, "s", ...variable amount of parameters...);<----how should this be handled?
...
答案 0 :(得分:2)
更新2 :如果您遇到此代码的任何其他问题,那么您应该关注this advice并改用PDO。
这是您应该使用call_user_func_array
[docs]的方式:
protected static function query($query, $types, $values) {
if($statement = mysqli_prepare(one::$db, $query) {
$parameters = array_merge(array($statement, $types), $values);
call_user_func_array('mysqli_stmt_bind_param', $parameters);
// ...
}
}
其中$types
是一个字符串,表示每个值的类型,如mysqli_stmt_bind_param
documentation中所述(call_user_func_array
甚至在那里提到过。)
更新:毕竟 似乎不容易,你必须先创建对这些值的引用:
foreach($values as $k => $v) {
$values[$k] = &$v;
}
$parameters = array_merge(array($statement, $types), $values);
call_user_func_array('mysqli_stmt_bind_param', $parameters);
// ...
call_user_func_array
用于每个php.net的用户定义函数
不,不是。第一个参数是callback
类型,documentation表示(强调我的):
PHP函数的名称作为字符串传递。 可以使用任何内置的或用户定义的函数,除了语言结构,例如:array(),echo(),empty(),eval(),exit(),isset(), list(),print()或unset()。
下一句话:
仅用于简化将数组传递给用户定义函数的语法
你看过这些例子了吗?传递给call_user_func_array
的数组的每个元素都将作为参数传递给您指定的函数。数组是获得可变大小值的唯一方法。
答案 1 :(得分:0)
因为我发现准备好的陈述很无聊,我手动处理占位符,并且不会遇到任何问题
private function prepareQuery($args)
{
$raw = $query = array_shift($args);
preg_match_all('~(\?[a-z?])~',$query,$m,PREG_OFFSET_CAPTURE);
$pholders = $m[1];
$count = 0;
foreach ($pholders as $i => $p)
{
if ($p[0] != '??')
{
$count++;
}
}
if ( $count != count($args) )
{
throw new E_DB_MySQL_parser("Number of args (".count($args).") doesn't match number of placeholders ($count) in [$raw]");
}
$shift = 0;
$qmarks = 0;
foreach ($pholders as $i => $p)
{
$pholder = $p[0];
$offset = $p[1] + $shift;
if ($pholder != '??')
{
$value = $args[$i-$qmarks];
}
switch ($pholder)
{
case '?n':
$value = $this->escapeIdent($value);
break;
case '?s':
$value = $this->escapeString($value);
break;
case '?i':
$value = $this->escapeInt($value);
break;
case '?a':
$value = $this->createIN($value);
break;
case '?u':
$value = $this->createSET($value);
break;
case '??':
$value = '?';
$qmarks++;
break;
default:
throw new E_DB_MySQL_parser("Unknown placeholder type ($pholder) in [$raw]");
}
$query = substr_replace($query,$value,$offset,2);
$shift+= strlen($value) - strlen($pholder);
}
$this->lastquery = $query;
return $query;
}
因此插入查询可以像
一样简单地调用$db->run("INSERT INTO table SET ?u",$data);
答案 2 :(得分:0)
我已经添加了完整的代码来为select prepared语句创建单个方法并插入预准备语句,请按照说明阅读所有注释。 使用名称&#39; test&#39;创建数据库并添加以下查询以创建&#34;用户&#34;
中的表格CREATE TABLE IF NOT EXISTS `users` (
`users_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`first_name` varchar(100) NOT NULL,
`last_name` varchar(100) NOT NULL,
PRIMARY KEY (`users_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=10 ;
INSERT INTO `users` (`users_id`, `first_name`, `last_name`) VALUES
(1, 'daniel', 'martin'),
(2, 'daniel', 'martin');
<?php
error_reporting(E_ALL);
ini_set('display_errors',1);
session_start();
class mysqli_access extends mysqli{
private $ip1;
private $dbconn;
private $hostname = HST; // hostname
private $username = USR; // username
private $password = PWD; // password
private $dbname = DBN; // datbase name
function mysqli_access()
{
$ip= $_SERVER['REMOTE_ADDR'];
$ip1="ip_".str_replace('.', "", $ip);
if(!is_resource($_SESSION[$ip1]))
{
$this->dbconn = new mysqli($this->hostname,$this->username,$this->password,$this->dbname);
$_SESSION[$ip1] = $this->dbconn;
$dbconn = $this->dbconn;
if( $this->connect_error ) {
$this->Display_error('', $this->connect_errno, $this->connect_error, __FUNCTION__);
}
}
else {
$this->dbconn = $_SESSION[$ip1]; // success
}
return $this->dbconn;
}
function SelectPrepared($sql,$types,$params,$rows = '')
{
$results = array();
if ($stmt = $this->dbconn->prepare($sql)) {
if($types&&$params)
{
$bind_names[] = $types;
for ($i=0; $i<count($params);$i++)
{
$bind_name = 'bind' . $i;
$$bind_name = $params[$i];
$bind_names[] = &$$bind_name;
}
$return = call_user_func_array(array($stmt,'bind_param'),$bind_names);
}
$stmt->execute(); /* execute query */
$meta = $stmt->result_metadata();
while ($field = $meta->fetch_field()) {
$var = $field->name;
$$var = null;
$fields_arr[$var] = &$$var;
}
call_user_func_array(array($stmt,'bind_result'),$fields_arr);
if($rows == 1){
while ($stmt->fetch()) {
$results = array();
foreach($fields_arr as $k => $v)
$results[$k] = $v;
}
}else{
$i = 0;
while ($stmt->fetch()) {
$results[$i] = array();
foreach($fields_arr as $k => $v)
$results[$i][$k] = $v;
$i++;
}
}
return $results;
}
}
public function InsertPrepared($tblName,$arrFieldNameValue,$replace_flag=0){
$TableName = $tblName;
if($replace_flag==0)
{
$sqlFirst ="INSERT INTO " . $TableName . "(";
}
if($replace_flag==1)
{
$sqlFirst ="INSERT IGNORE INTO " . $TableName . "(";
}
if($replace_flag==2)
{
$sqlFirst ="REPLACE INTO " . $TableName . "(";
}
$sqlSecond =" values(";
$params = array();
$types = '';
while(list($key,$value) = each($arrFieldNameValue))
{
$sqlFirst = $sqlFirst . $key . ",";
$sqlSecond = $sqlSecond . '?' . ",";
$params[] = $value;
$types = $types . $this->GetValType($value);
}
$sqlFirst = substr($sqlFirst,0,strlen($sqlFirst)-1) . ") ";
$sqlSecond = substr($sqlSecond,0,strlen($sqlSecond)-1) .")";
$sql = $sqlFirst . $sqlSecond;
if ($stmt = $this->dbconn->prepare($sql)) {
if($types&&$params)
{
$bind_names[] = $types;
for ($i=0; $i<count($params);$i++)
{
$bind_name = 'bind' . $i;
$$bind_name = $params[$i];
$bind_names[] = &$$bind_name;
}
$return = call_user_func_array(array($stmt,'bind_param'),$bind_names);
}
$stmt->execute(); /* execute query */
}
return mysqli_insert_id($this->dbconn);
}
private function GetValType($Item)
{
switch (gettype($Item)) {
case 'NULL':
case 'string':
return 's';
break;
case 'integer':
return 'i';
break;
case 'blob':
return 'b';
break;
case 'double':
return 'd';
break;
}
return 's';
}
}
class Model_NAME extends mysqli_access
{
function Model_NAME() {
$this->tablename = TABLENAME;
$this->mysqli_access();
}
##---------------------------- Custom function start from here -----------------#
## fetch settings values
function getUserRow($id,$key) {
$sql ="SELECT first_name,last_name FROM ".$this->tablename." WHERE first_name=? and users_id = ?";
$param = "si";
$array_of_params[] = addslashes($key);
$array_of_params[] = addslashes($id);
$result= $this->SelectPrepared($sql,$param,$array_of_params,1);
//last parameter 1 use if want fetch single row , other wise function will return multi dimensional array
return $result;
}
## fetch settings values
function getUserRows($last_name) {
$sql ="SELECT first_name,last_name FROM ".$this->tablename." WHERE last_name= ?";
$param = "s";
$array_of_params[] = addslashes($last_name);
$result= $this->SelectPrepared($sql,$param,$array_of_params);
//last parameter 1 use if want fetch single row , other wise function will return multi dimensional array
return $result;
}
function addValue($Array) {
return $this->InsertPrepared( $this->tablename , $Array);
}
}
// configuration
define('HST','localhost');
define('USR','root');
define('PWD','techmodi');
define('DBN','test');
define('TABLENAME','users');
$obj = new Model_NAME();
$arr = array();
$arr['first_name'] = addslashes("daniel");
$arr['last_name'] = addslashes("martin");
$obj->addValue($arr); // for insert records
// after inserting get the records
$singleRow = $obj->getUserRow(1,'daniel'); // for select single records
$multiRow =$obj->getUserRows('martin'); // for select records
echo '<pre>';
echo '<br/>-------- Single Records -----------------<br/>';
print_r($singleRow);
echo '<br/>-------- Multiple Records-----------------<br/>';
print_r($multiRow);
?>