如何在PHP中同时处理撇号和双引号

如何在PHP中同时处理撇号和双引号,php,string,escaping,Php,String,Escaping,我有一个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'"

我有一个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\u query()
时会出现错误。 因此,即使我在初始化
$sent
时转义了双引号,它仍然会给
mysqli\u query()
的执行带来问题。如果我同时转义'And',则
$sent
的值并没有保持它实际需要的值(尽管我不确定同时转义'And'是否有效)

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


[p.S.我已经搜索了stackoverflow之前的一些问题,但还没有找到解决方案。]

您需要什么,您应该做的是使用准备好的语句(参数化查询)。使用
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)-有关详细信息,请参阅:

$stmt = $mysqli->prepare('SELECT * FROM myrecord WHERE sentence = ?');
//or $stmt = mysqli_prepare($connection, $query);
然后,使用以下命令绑定参数(WHERE子句中要使用的值):

然后调用-or
mysqli\u stmt\u execute
,并使用-or
mysqli\u stmt\u fetch
获取结果


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

$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:不,
:句子是占位符,它不是查询的实际部分。其工作方式是将带有占位符的查询发送到DB,在DB中对其进行解析并生成执行计划,然后在调用
execute
时,单独发送参数值并将其放置到位,然后执行生成的查询。结果是,不再需要像引号那样转义字符,因为参数和查询字符串本质上是独立处理的。另一个优点是,您可以重复使用准备好的语句(我将用一个示例更新答案)
$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();
}