如何在SQL查询中使用prepared和bound语句

时间:2011-02-23 20:25:10

标签: php oop mysqli prepared-statement

我被告知下面的查询非常容易被SQL注入 - 我应该使用绑定参数,

class search
{

    public $mysqli = null;

    public function __construct($mysqli,$keyword = null)
    {
       $this->mysqli = $mysqli;
    }

    public function get_result($parameter)
    {
        $sql = "
        SELECT *
        FROM root_contacts_cfm
        WHERE root_contacts_cfm.cnt_id = '".$parameter."'
        ORDER BY cnt_id DESC
        ";

        $item = $this->mysqli->fetch_assoc($sql);
        return $item;
    }
}

我可以问 - 如何用准备好的约束语句来转换这个search类?

我在线阅读了一些文章,为什么我们应该使用准备好的陈述, article 1 article 2

但我仍然不知道如何改进我的查询......我尝试了下面的修正案,

class search
{

    public $mysqli = null;

    public function __construct($mysqli)
    {
       $this->mysqli = $mysqli;
    }

    public function get_result($parameter)
    {
        $sql = "
        SELECT *
        FROM root_contacts_cfm
        WHERE root_contacts_cfm.cnt_id = '?'
        ORDER BY cnt_id DESC
        ";

        $stmt = $this->mysqli->prepare($sql);

        /* bind parameters for markers */
        $stmt->bind_param("s", $parameter);

        /* execute query */
        $stmt->execute();

         /* fetch value */
        return $stmt->fetch();

    }
}

因此,当我将搜索类称为对象时,

$mysqli = new database(DB_HOST,DB_USER,DB_PASS,DB_NAME);
$output = new search($mysqli);
print_r($output->get_result('1'));

我会收到此错误,

  

警告:mysqli_stmt :: bind_param()   [mysqli-stmt.bind-param]:数量   变量与数量不匹配   准备好的声明中的参数   C:\ wamp \ www \ xxxl \ class_database.php on   第487行

第487行是指$stmt->bind_param("s", $parameter);

感谢。

2 个答案:

答案 0 :(得分:1)

尝试删除'占位符周围的?

$sql = "
SELECT *
FROM root_contacts_cfm
WHERE root_contacts_cfm.cnt_id = ?
ORDER BY cnt_id DESC
";

在准备好的语句中,整个事情是关于在绑定它时指定param的类型,而不是在SQL查询中 - 当你写'?'时你做了。您已经说过,当您将param绑定为字符串时,必须是字符串,但不是必需的。数据库引擎现在将如何插入/转义该值。

答案 1 :(得分:0)

这是我在网上搜索后的解决方案:

class search
{
    public $mysqli = null;

    public function __construct($mysqli)
    {
       $this->mysqli = $mysqli;
    }

    public function get_result($parameter)
    {
        $sql = "
        SELECT *
        FROM root_contacts_cfm
        WHERE root_contacts_cfm.cnt_id = ?
        ORDER BY cnt_id DESC
        ";

        # create a prepared statement
        $stmt = $this->mysqli->prepare($sql);

        # bind parameters for markers
        $stmt->bind_param("s", $parameter);

        # execute query 
        $stmt->execute();



        /*
        # these lines of code below return multi-dimentional array, similar to mysqli::fetch_all()
        $stmt->store_result();

        $variables = array();
        $data = array();
        $meta = $stmt->result_metadata();

        while($field = $meta->fetch_field())
            $variables[] = &$data[$field->name]; // pass by reference

        call_user_func_array(array($stmt, 'bind_result'), $variables);

        $i=0;
        while($stmt->fetch())
        {
            $array[$i] = array();
            foreach($data as $k=>$v)
                $array[$i][$k] = $v;
            $i++;
        }

        return $array;
        */

        # these lines of code below return one dimentional array, similar to mysqli::fetch_assoc()
        $meta = $stmt->result_metadata(); 

        while ($field = $meta->fetch_field()) { 
            $var = $field->name; 
            $$var = null; 
            $parameters[$field->name] = &$$var; 
        }

        call_user_func_array(array($stmt, 'bind_result'), $parameters); 

        while($stmt->fetch()) 
        { 
            return $parameters;
            //print_r($parameters);      
        } 

        # the commented lines below will return values but not arrays
        # bind result variables
        //$stmt->bind_result($id); 

        # fetch value
        //$stmt->fetch(); 

        # return the value
        //return $id; 

        # close statement
        $stmt->close();
    }
}

虽然不太明白......

我发现很难理解和练习准备和绑定语句... mysqli :: query()更容易让我理解......