mysqli:严格标准:只应通过引用传递变量

时间:2014-05-24 09:25:42

标签: php object mysqli

我正在尝试创建一个小型SQL查询类。

这是我的课程,但我不知道为什么,我发现了这个错误: 严格标准:在第52行中只能通过引用传递变量

第52行是:

if (!$stmt->bind_param($param[$i][0], mysqli_real_escape_string($this->mysqli, $param[$i][1]))) {

我的代码(我开始):

<?php
class Sql{

    private $db;
    private $user;
    private $pwd;
    private $url;

    private $param;

    private $mysqli;

    function __construct($db, $user, $pwd, $url){
        $this->db = $db;
        $this->user = $user;
        $this->pwd = $pwd;
        $this->url = $url;


    }

    /**
     * mysqli::connection()
     * 
     * @return 
     */
    public function connection()
    {
        try{
            $this->mysqli = new mysqli($this->db, $this->user, $this->pwd, $this->url);
        }catch(Exception $e){
            throw new Exception("Impossible de se connecter à la base " . $this->db);
        }
    }

    public function select($query, $param, $debug=false){

        $this->connection();

        $r = $this->InitialiseResult("select");

        if (!($stmt = $this->mysqli->prepare($query))) {
            echo "Echec de la préparation : (" . $this->mysqli->errno . ") " . $this->mysqli->error;
        }

        //Param
        for($i=0;$i<sizeof($param);$i++){
            if (!$stmt->bind_param($param[$i][0], mysqli_real_escape_string($this->mysqli, $param[$i][1]))) {
                echo "Echec lors du liage des paramètres : (" . $stmt->errno . ") " . $stmt->error;
            }
        }

        if (!$stmt->execute()) {
            echo "Echec lors de l'exécution : (" . $stmt->errno . ") " . $stmt->error;
        }

        if (!($res = $stmt->get_result())) {
            echo "Echec lors de la récupération du jeu de résultats : (" . $stmt->errno . ") " . $stmt->error;
        }else{

            $r["state"] = true;
            $r["rows"] = $res->fetch_assoc();
            $r["num_rows"] = $res->num_rows;

            if($debug)
                var_dump($r);

        }

        return $r;

    }


    /**
     * mysqli::InitialiseResult()
     *
     * @param mixed $p
     * @return
     */
    public function InitialiseResult($p)
    {
        $r = array(); //on écrase
        $r["state"] = false;

        switch($p){
            case "select":

                $r["rows"] = array();
                $r["num_rows"] = 0;
                break;

        }

        return $r;
    }
}
?>

我尝试将$ param放在属性中并使用mysqli_real_escape_string(),但错误仍然存​​在。

有什么想法吗?

2 个答案:

答案 0 :(得分:2)

$stmt->bind_param()要求所有参数都通过引用传递,因此您无法直接传递函数的返回值(而不是首先将其赋值给变量,即)。但是,正如评论中已经提到的那样,您根本不需要逃避参数,这是使用预准备语句的优势之一。

答案 1 :(得分:2)

mysqli_stmt::bind_param期望第二个和以下任何参数都是变量,因为它是passed by reference,在参数之前由&表示:

bool mysqli_stmt::bind_param ( string $types , mixed &$var1 [, mixed &$... ] )

在内部,PHP不存储实际值,而只存储对保存该值的变量的引用。并且仅在执行预准备语句时获取实际值。这就是为什么你不能绑定值而只能绑定变量。

但是,由于这个原因,可以执行以下操作:

$stmt = $mysqli->prepare('INSERT INTO table (a, b) VALUES (?, ?)');
$stmt->bind_param(1, $a);
$stmt->bind_param(2, $b);

$pairs = array(
    array('a1', 'b1'),
    array('a2', 'b2'),
    array('a3', 'b3'),
);    

foreach ($pairs as $pair) {
    list($a, $b) = $pair;
    $stmt->execute();
}

INSERT语句已准备好,其参数仅绑定一次,但多次使用不同的参数值执行。更改变量值不会破坏变量引用。


但是,对于您的实际问题,您根本不需要也不应该在准备语句的参数上使用mysqli_real_escape_string。只需绑定变量,MySQLi就可以完成其余的工作。