【问题标题】:How to deal with apostrophes and double quotes simultaneously in PHP如何在 PHP 中同时处理撇号和双引号
【发布时间】:2016-09-02 15:00:49
【问题描述】:

我有一个 HTML 表单,一个 PHP 脚本从中提取值,如下所示:

$dbc = mysqli_connect("all required info here...") or die("Error occurred");

$sent = "Any sentence here...which may contain apostrophe or double quotes or both";

$query = "SELECT * FROM myrecord WHERE sentence = '$sent'";
$result = mysqli_query($dbc, $query);
$data = mysqli_fetch_array($result);
mysqli_close($dbc);

问题是,变量$sent 可以包含任何带有撇号或双引号或两者的组合 的字符串。这在执行mysqli_query() 时会出错。 所以即使我在$sent 的初始化中转义双引号,它仍然会为mysqli_query() 的执行带来问题。如果我同时转义 ' 和 " 则 $sent 的值不会保持它实际需要的值(尽管我不确定同时转义 ' 和 " 是否会起作用)。

是否有任何内置函数可以自动转义字符串的所有特殊字符?或者有什么办法可以解决这个问题?

[附注我已经搜索了一些关于stackoverflow的以前的问题,但未能找到解决方案。]

【问题讨论】:

    标签: php string escaping


    【解决方案1】:

    你想要什么,你应该做什么是使用准备好的语句(参数化查询)。使用PDO,看起来像这样:

    $stmt = $pdo->prepare('SELECT * FROM myrecord WHERE sentence = :sentence');
    $stmt->execute([':sentence' => $sentence]);
    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
        //do stuff
    }
    

    mysqli 也支持它们,但 API 稍微麻烦一些 (IMO) - 请参阅 mysqli_prepare docs 了解详细信息:

    $stmt = $mysqli->prepare('SELECT * FROM myrecord WHERE sentence = ?');
    //or $stmt = mysqli_prepare($connection, $query);
    

    然后,使用bind_param 绑定参数(WHERE 子句中使用的值):

    $stmt->bind_param('s', $sentence);
    //or mysqli_stmt_bind_param($stmt, 's', $sentence);
    

    然后调用execute - 或mysqli_stmt_execute,并使用fetch - 或mysqli_stmt_fetch 获取结果...


    如 cmets 中所述:参数和查询字符串不需要以任何方式引用,因为它们被视为单独的实体。结果是您可以重复使用具有不同参数的相同准备好的语句:

    $stmt = $pdo->prepare('SELECT * FROM table WHERE field = :field');
    $fieldVals = [123, 46, 32]; // three values:
    $results = array_fill_keys($fieldVals, null);
    foreach ($fieldVals as $val) {
        $stmt->execute([':field' => $val]);//execute with each value in $fieldVals array
        $results[$val] = $stmt->fetchAll(PDO::FETCH_ASSOC); // fetch results for this field value
        //optional, but good form:
        $stmt->closeCursor();
    }
    

    您现在已经使用了 3 次相同的语句,但只需要发送查询字符串 一次。查询必须解析和处理一次,之后,您只需将参数发送到数据库。这种方法通常更快、更安全(准备好的语句可以防止大多数注入攻击),而且全面更好。

    【讨论】:

    • 如果字符串包含撇号,这不会在$pdo->prepare() 中造成麻烦吗?
    • @Lincoln 你不再需要使用撇号了。
    • @Lincoln:不,:sentence 是一个占位符,它不是查询的实际部分。它的工作方式是查询,将占位符发送到数据库,在那里对其进行解析并构建执行计划,然后,在调用execute 时,参数值被单独发送并放置到位,resulting 查询被执行。结果是,不再需要转义引号之类的字符,因为参数和查询字符串本质上是独立处理的。另一个好处是你可以重复使用准备好的语句(我会用一个例子来更新答案)
    猜你喜欢
    • 2012-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-19
    • 2019-02-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多