在PHP中使用MySQLi Prepared Statements的最佳方法

时间:2013-12-19 07:51:31

标签: php mysqli prepared-statement

我是准备好的陈述的新手。我已经理解了它的使用以及如何使用它。我想知道,在哪里放置语句和类似的东西。 我是否应该在每个要查询数据库的文件中准备一个(或多个)语句?另外,您能举例说明以程序方式使用预准备语句吗?

我试过这样做。虽然它没有用。

include 'db/connect.php';

$query = "SELECT * FROM `users` WHERE `id` = ?";
$i  = 5;
$statement = $connect->prepare($query);
$statement->bind_param('i', $i);
$statement->execute();

while($row = mysqli_fetch_assoc($statement)){
    echo $row['email'].'<br>';
}

3 个答案:

答案 0 :(得分:1)

一种程序性的方式......哼哼,自从我做了一些程序性的(很严格的非OOP)以来已经很久了。我不知道你为什么要限制自己,但我仍然会离开PDO,因为这是最好的做法(来自我的POV)

  

我应该在每个要查询数据库的文件中准备一个(或多个)语句吗?

我认为您应该根据需要准备尽可能多的查询并封装您的功能,这样您就不必复制粘贴

您的includes.php文件中的

定义可在许多地方使用的功能

/**
 * Get User by Id
 * @returns user object or null
 */
function getUserById(PDO $connection, $id) {
  $q = 'SELECT * FROM `users` WHERE `id`=?';
  $stmt = $connection->prepare($q);
  $stmt->execute(array($id));
  return $stmt->fetchObject();
}
您的db/connect.php文件

中的

设置PDO连接(这是我的个人推荐,我有偏见)

// do not copy paste, check the manual to see for yourself how it is done
$dsn = 'mysql:host='.$host.';dbname='.$data;
$connection = new PDO($dsn,$user,$password);

使用

只要您需要get a user by his id只需将数据库连接(PDO对象)和$id传递给函数

// functionality has been encapsulated and may be reused
$user = getUserById($connection,$id);

答案 1 :(得分:1)

我已经添加了完整的代码来为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);
?>

答案 2 :(得分:0)

准备好的语句阻止SQL注入。 PHP具有很棒的扩展名“ mysqli_”,它能够执行准备好的语句。

我应该在要查询数据库的每个文件中准备一个(或多个)语句吗? 答案是肯定的。您应该在每个文件中准备语句。 (如果要在多个页面中执行相同的查询,则将代码保存在一个文件中,并在需要时将其包括在内)

这行不通吗? 是的,准备好的语句通常会出错(在编写准备好的语句时会出错)。因此,知道如何调试这些语句确实很有用。首先,让我们像下面那样更改代码。

include 'db/connect.php';

$query = "SELECT * FROM `users` WHERE `id` = ?";
$i  = 5;
$statement = $connect->prepare($query);
if (
  $statement &&
  $statement->bind_param('i', $i) &&
  $statement->execute()
) {
  while($row = mysqli_fetch_assoc($statement)){
    echo $row['email'].'<br>';
  }
} else {
  echo $connect -> error; // if you have an error in the query
  echo $statement -> error; // if you have an error in bind_param() or execute()
}   

好!这样,您可以轻松地发现查询或代码中的任何错误。并且,使用上面的if语句将帮助您防止许多错误,并且仅在最后一个成功的情况下继续执行代码。

这可能会更好。但是,经过几年的试验,我发现此方法是最好的方法。有关此概念的所有内容均写在本文中:

The Best Way to Perform MYSQLI Prepared Statements in PHP

谢谢!