首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MySQLi: query VS prepare

MySQLi: query VS prepare
EN

Stack Overflow用户
提问于 2011-02-25 01:44:21
回答 2查看 15.6K关注 0票数 10

有一件事我一点也不理解,那就是mysqli中的preparequery

这是使用mysqli::query来处理查询,众所周知,它缺乏安全性:

代码语言:javascript
复制
public function fetch_assoc($query)
    {
        $result = parent::query($query);
        //$result = self::preparedStatement($query);
        if($result) 
        {
            return $result->fetch_assoc();
        } 
        else
        {
            # call the get_error function
            return self::get_error();
            # or:
            # return $this->get_error();
        }
    }

这是一个准备-绑定-执行的版本,我认为它有更好的安全性,

代码语言:javascript
复制
public function fetch_assoc_stmt($sql,$types = null,$params = null)
    {
        # create a prepared statement
        $stmt = parent::prepare($sql);

        # bind parameters for markers
        # but this is not dynamic enough...
        //$stmt->bind_param("s", $parameter);

        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);
        }

        # execute query 
        $stmt->execute();

        # 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;  
        }

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

然而,这两种方法都返回相同的结果。

代码语言:javascript
复制
$mysqli = new database(DB_HOST,DB_USER,DB_PASS,DB_NAME);

$sql = "
SELECT *
FROM root_contacts_cfm
ORDER BY cnt_id DESC
";
print_r($mysqli->fetch_assoc_stmt($sql));

print_r($mysqli->fetch_assoc($sql));

他们会打印如下内容:

代码语言:javascript
复制
Array
(
    [cnt_id] => 2
    [cnt_email1] => lau@xx.net
    [cnt_email2] => 
    [cnt_fullname] => Lau T
    [cnt_firstname] => Thiam
    [cnt_lastname] => Lau
    [cnt_organisation] => 
    [cnt_website] => 
    [cnt_biography] => 
    [cnt_gender] => 
    [cnt_birthday] => 
    [cnt_address] => 
    [cnt_postcode] => 
    [cnt_telephone] => 
    [cnt_note] => 
    [cnt_key] => 
    [cat_id] => 
    [tcc_id] => 
    [cnt_suspended] => 0
    [cnt_created] => 2011-02-04 00:00:00
    [cnt_updated] => 2011-02-04 13:54:36
)
Array
(
    [cnt_id] => 2
    [cnt_email1] => lau@xx.net
    [cnt_email2] => 
    [cnt_fullname] => Lau T
    [cnt_firstname] => Thiam
    [cnt_lastname] => Lau
    [cnt_organisation] => 
    [cnt_website] => 
    [cnt_biography] => 
    [cnt_gender] => 
    [cnt_birthday] => 
    [cnt_address] => 
    [cnt_postcode] => 
    [cnt_telephone] => 
    [cnt_note] => 
    [cnt_key] => 
    [cat_id] => 
    [tcc_id] => 
    [cnt_suspended] => 0
    [cnt_created] => 2011-02-04 00:00:00
    [cnt_updated] => 2011-02-04 13:54:36
)

您应该已经注意到,在fetch_assoc_stmt的方法中,我根本没有使用fetch_assoc。可能根本没有机会使用它,因为prepare使用不同的方式来返回结果。

所以,我的问题是,既然使用prepare比使用query更好,那么fetch_assoc为什么要存在呢?难道我们不应该忘记它,或者php.net不应该将其弃用吗?对于fetch_all也是如此--为什么我们首先要拥有它!??

谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-02-25 02:10:59

当您使用参数动态生成查询时,预准备语句比普通SQL查询更可取。在您的示例中,您的SQL不包含变量,因此使用普通查询或准备好的语句在功能上是等效的。

当您必须更改参数的值时,例如,在WHERE子句中,预准备语句将为您提供更高的安全性:

代码语言:javascript
复制
...
WHERE col1 = ? AND col2 = ?

但是当您的查询简单且固定时,使用$mysqli->query($sql)fetch_assoc()可能需要更少的代码。使用直接查询而不是预准备语句并不是一个普遍的坏做法,因为有些人可能会让您相信这一点。当您的查询需要参数化时,或者当必须重复编译和执行相同的查询时,您将受益于预准备语句。

票数 22
EN

Stack Overflow用户

发布于 2011-06-29 03:43:49

很抱歉,这不是一个答案,但我不够好,实际上没有留下评论。

看起来你的第二个函数有一个bug。对于返回多行的查询,您的代码将无法正常工作。返回语句不应该是:

代码语言:javascript
复制
while($stmt->fetch()) {

    //to dereference
    $row_copy = $parameters;
    $return_array[] = $row_copy;

}

然后该函数应该以以下形式结束:

代码语言:javascript
复制
return $return_array;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5108414

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档