准备好的陈述 - 创建单一方法*

时间:2011-09-11 20:34:14

标签: php

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?
      ...

3 个答案:

答案 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);
?>