zoukankan      html  css  js  c++  java
  • PHP中对mysql预编译查询语句的一个封装

    原文地址:http://chen-shan.net/?p=474

    为了防止sql注入,我们都使用过mysqli这个类,但是每次都需要绑定参数,绑定结果等,比较麻烦,所以可以把这些重复的语句封装成一个函数.

    一.封装前.

    传统的一个预编译方式的”select”查询代码:

    $id = "1";
    $name = "test_name";
    
    $db_obj = new mysqli("localhost", "db_user", "db_passwd", "db");
    $db_obj->set_charset("utf8");
    
    $query = "SELECT column1, column2, column3, column4 FROM tb_test WHERE id = ? and name = ?";
    $stmt = $db_obj->prepare($query);
    $stmt->bind_param("is", $id, $name);
    $stmt->execute();
    
    $stmt->bind_result($column1, $column2, $column3, $column4);
    while ($stmt->fetch()) {
        $result = array();
        $result['column1'] = $column1;
        $result['column2'] = $column2;
        $result['column3'] = $column3;
        $result['column4'] = $column4;
        $results[] = $result;    
    }
    
    /* The result stored in array $results */
    print_r($results);

    二.封装后.

    封装函数 (忘了是根据php手册中哪条评论修改得来的了) 如下:

    /*
     * 执行预编译形式的mysql语句
     * 
     * @$query       (string)  --  查询语句,例如:"SELECT * FROM table WHERE id = ?"
     * @$params     (array)  --  绑定参数,例如:array('i', $id)
     * @$resultFlag (string)  --  是否为含有返回结果的查询,注意!!!: 为“select”查询时为“false”,为“insert”,"delete" 与 "update" 时为“true”
     * @$closeFlag  (string)  --  是否关闭数据库连接句柄, 关闭为 "ture", 不关闭为 "false"
     */
    
    function _queryStmt($db_obj, $query, $params, $resultFlag, $closeFlag) {
        $mysqli = $db_obj;
    
        $stmt = $mysqli->prepare($query);
        call_user_func_array(array($stmt, 'bind_param'), _refValues($params));   //绑定参数
        $stmt->execute();
    
        //$resultFlag为true,则为“insert”,"delete" 与 "update"操作,无需绑定结果;false则为 “select”操作,需要绑定查询结果.
        if ($resultFlag) {
    
            $result = $mysqli->affected_rows;   //进行了修改的行数
    
        } else {
    
            $meta = $stmt->result_metadata();
    
            //将结果绑定数组元素设置为引用状态,因为call_user_func_array(array($stmt, 'bind_result'), $parameters)中的回调函数参数$parameters需要引用状态.
            while ($field = $meta->fetch_field()) {
                $parameters[] = &$row[$field->name];
            }
    
            call_user_func_array(array($stmt, 'bind_result'), _refValues($parameters));  //绑定结果
    
            //有多行记录时将多行记录存入$results数组中.
            while ($stmt->fetch()) {
                $x = array();
                foreach ($row as $key => $val) {
                    $x[$key] = $val;
                }
                $results[] = $x;
            }
    
            $result = $results;
        }
    
        $stmt->close();
    
        //$closeFlag为true则需要关闭数据库句柄
        if($closeFlag) {
            $mysqli->close();
        }
    
        return $result;
    }
    
    /*
     * 作用:把返回的数组中的元素变为引用状态.
     * (如果$arr为含有引用状态元素的数组,则会影响调用者的参数数组,反之则反)
     */
    
    function _refValues($arr) {
        if (strnatcmp(phpversion(), '5.3') >= 0) { //Reference is required for PHP 5.3+
            $refs = array();
            foreach ($arr as $key => $value) {
                $refs[$key] = &$arr[$key];
            }
            return $refs;
        }
        return $arr;
    }

    封装函数中有两点需要注意:一个是mysqli_stmt::bind_param方法与mysqli_stmt::bind_result方法都为可变函数,所以需要使用call_user_func_array()这个函数进行回调;第二个是以上两个方法所需要的参数都为引用形式,所以在使用call_user_func_array()函数进行回调时要特别小心,所以才有封装函数中_refValues()的必要.

    调用如下:

    $id = "1";
    $name = "test_name";
    
    $db_obj = new mysqli("localhost", "db_user", "db_passwd", "db");
    $db_obj->set_charset("utf8");
    
    $query = "SELECT column1, column2, column3, column4 FROM tb_test WHERE uid = ? and name = ?";
    $params = array("is", $id, $name);
    $results = _queryStmt($db_obj, $query, $params, FALSE, TRUE);
    
    /* The result stored in array $results */
    print_r($results);

    这里只是举例了 “SELECT” 语句,此函数还可以应用于 “INSERT”, “DELETE”, “UPDATE”等, 只是要注意把函数_queryStmt()中的第四个参数设为 TRUE,因为没有记录数据的返回.

    封装的函数也可以当作你mysql操作类中的一个方法.使用形式可以多种多样!

  • 相关阅读:
    厦门,第二天
    react结合redux开发
    react native中使用ScrollableTabView
    react native中使用 react-native-easy-toast 和react-native-htmlview
    react native中使用native-echarts
    react native 使用TabNavigator编写APP底部导航
    react native 初识生命周期
    react native初识
    禁止浏览器返回登入页面
    vue中使用echarts来绘制世界地图和中国地图
  • 原文地址:https://www.cnblogs.com/chenshuo/p/4729514.html
Copyright © 2011-2022 走看看