mysqli::real_escape_string

mysqli_real_escape_string

(PHP 5, PHP 7, PHP 8)

mysqli::real_escape_string -- mysqli_real_escape_string转义字符串中的特殊字符以用于 SQL 语句,并考虑连接的当前字符集

描述

面向对象风格

public mysqli::real_escape_string(string $string): string

过程式风格

mysqli_real_escape_string(mysqli $mysql, string $string): string

此函数用于创建可以在 SQL 语句中使用的合法 SQL 字符串。给定字符串被编码以生成转义的 SQL 字符串,并考虑连接的当前字符集。

注意

安全性:默认字符集

字符集必须在服务器级别设置,或者使用 API 函数 mysqli_set_charset() 设置,才能影响 mysqli_real_escape_string()。有关更多信息,请参见关于 字符集 的概念部分。

参数

mysql

仅限过程式风格:由 mysqli_connect()mysqli_init() 返回的 mysqli 对象

string

要转义的字符串。

编码的字符是 NUL (ASCII 0)\n\r\'"CTRL+Z

返回值

返回转义的字符串。

示例

示例 #1 mysqli::real_escape_string() 示例

面向对象风格

<?php

mysqli_report
(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

$city = "'s-Hertogenbosch";

/* 此查询使用转义的 $city 将正常工作 */
$query = sprintf("SELECT CountryCode FROM City WHERE name='%s'",
$mysqli->real_escape_string($city));
$result = $mysqli->query($query);
printf("Select 返回 %d 行。\n", $result->num_rows);

/* 此查询将失败,因为我们没有转义 $city */
$query = sprintf("SELECT CountryCode FROM City WHERE name='%s'", $city);
$result = $mysqli->query($query);

过程式风格

<?php

mysqli_report
(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = mysqli_connect("localhost", "my_user", "my_password", "world");

$city = "'s-Hertogenbosch";

/* 此查询使用转义的 $city 将正常工作 */
$query = sprintf("SELECT CountryCode FROM City WHERE name='%s'",
mysqli_real_escape_string($mysqli, $city));
$result = mysqli_query($mysqli, $query);
printf("Select 返回 %d 行。\n", mysqli_num_rows($result));

/* 此查询将失败,因为我们没有转义 $city */
$query = sprintf("SELECT CountryCode FROM City WHERE name='%s'", $city);
$result = mysqli_query($mysqli, $query);

上面的示例将输出类似于以下内容

Select returned 1 rows.

Fatal error: Uncaught mysqli_sql_exception: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 's-Hertogenbosch'' at line 1 in...

参见

添加注释

用户贡献的注释 7 个注释

58
dave at mausner.us
13 年前
如果您使用 prepare() 和 bind_param() 作为将任意字符串值放入 SQL 语句的替代方法,则可以避免所有字符转义问题(在 PHP 方面)。这是因为绑定参数值不是通过 SQL 语句语法传递的。
51
Josef Toman
14 年前
对于百分号和下划线,我使用以下方法
<?php
$more_escaped
= addcslashes($escaped, '%_');
?>
39
arnoud at procurios dot nl
19 年前
请注意,此函数不会转义 _(下划线)和 %(百分号),它们在 LIKE 子句中具有特殊含义。

据我所知,没有函数可以做到这一点,因此您必须自己转义它们,在它们前面添加反斜杠。
21
therselman at gmail dot com
7 年前
介绍几个支持 UTF-8/多字节的转义函数。

只要您的数据库连接和多字节扩展使用相同的字符集(UTF-8),这些函数就代表了 mysqli::real_escape_string 的替代方案,它们将通过转义与 mysqli::real_escape_string 相同的字符来产生相同的结果。

这是基于我为我的 SQL 查询构建器类所做的研究
https://github.com/twister-php/sql

<?php
/**
* 返回一个字符串,其中在需要转义的字符之前添加反斜杠。
* 符合 MySQL 的要求,适合多字节字符集
* 编码的字符是 NUL(ASCII 0)、\n、\r、\、'、" 和 ctrl-Z。
*
* @param string $string 要添加反斜杠的字符串
* @return $string 在保留字符前添加 `\`
*
* @author Trevor Herselman
*/
if (function_exists('mb_ereg_replace'))
{
function
mb_escape(string $string)
{
return
mb_ereg_replace('[\x00\x0A\x0D\x1A\x22\x27\x5C]', '\\\0', $string);
}
} else {
function
mb_escape(string $string)
{
return
preg_replace('~[\x00\x0A\x0D\x1A\x22\x27\x5C]~u', '\\\$0', $string);
}
}

?>

转义的字符(与 mysqli::real_escape_string 相同)

00 = \0 (NUL)
0A = \n
0D = \r
1A = ctl-Z
22 = "
27 = '
5C = \

注意:preg_replace() 处于 PCRE_UTF8(UTF-8)模式 (`u`)。

增强版

在为 `LIKE` 语法转义字符串时,请记住还需要转义特殊字符 _ 和 %

所以这是一个更安全的版本(即使与 mysqli::real_escape_string 相比,因为用户输入中的 % 字符会导致意外结果,甚至会导致通过 LIKE 语句进行 SQL 注入的安全性问题)

<?php

/**
* 返回一个字符串,其中在需要转义的字符之前添加反斜杠。
* 符合 MySQL 的要求,适合多字节字符集
* 编码的字符是 NUL(ASCII 0)、\n、\r、\、'、" 和 ctrl-Z。
* 此外,还会转义特殊控制字符 % 和 _,
* 适合所有语句,但特别适合 `LIKE`。
*
* @param string $string 要添加反斜杠的字符串
* @return $string 在保留字符前添加 `\`
*
* @author Trevor Herselman
*/
if (function_exists('mb_ereg_replace'))
{
function
mb_escape(string $string)
{
return
mb_ereg_replace('[\x00\x0A\x0D\x1A\x22\x25\x27\x5C\x5F]', '\\\0', $string);
}
} else {
function
mb_escape(string $string)
{
return
preg_replace('~[\x00\x0A\x0D\x1A\x22\x25\x27\x5C\x5F]~u', '\\\$0', $string);
}
}

?>

其他转义的字符

25 = %
5F = _

附加函数

原始的 MySQL `utf8` 字符集(用于表和字段)只支持 3 字节序列。
4 字节字符并不常见,但我遇到过 4 字节 UTF-8 字符无法执行查询的情况,因此应尽可能使用 `utf8mb4`。

但是,如果您仍然想使用 `utf8`,可以使用以下函数来替换所有 4 字节序列。

<?php
// 修改自:https://stackoverflow.com/a/24672780/2726557
function mysql_utf8_sanitizer(string $str)
{
return
preg_replace('/[\x{10000}-\x{10FFFF}]/u', "\xEF\xBF\xBD", $str);
}
?>

选择你的毒药,后果自负!
15
匿名
9 年前
如果你想知道为什么(除了 \、' 和 ")NUL(ASCII 0)、\n、\r 和 Control-Z 会被转义:这并不是为了防止 SQL 注入,而是为了防止你的 SQL 日志文件变得不可读。
4
ASchmidt at Anamera dot net
3 年前
注意在转义 % 和 _ 通配符时要谨慎。根据

https://dev.mysqlserver.cn/doc/refman/5.7/en/string-literals.html#character-escape-sequences

底部的一条经常被忽略的说明,转义序列 \% 和 \_ 只会在 LIKE 中被解释为 % 和 _! (MySQL 8.0 也是如此)

在普通的字符串文字中,转义序列 \% 和 \_ 被视为这两个字符对。因此,如果这些转义序列出现在 WHERE "=" 中而不是 WHERE LIKE 中,它们将不会匹配单个 % 或 _ 字符!

因此,必须使用两个“转义”函数:一个用于普通字符串文字的 real-escape-string(或等效函数),另一个用于专门用于 LIKE 的字符串文字的修改后的转义函数。
-3
Lawrence DOliveiro
6 年前
注意,“like” 运算符要求对其特殊字符进行 *额外* 级别转义,*在* mysql_escape_string 执行的转义*之上*。但是,没有内置函数来执行此转义。这是一个执行此操作的函数

function escape_sql_wild($s)
/* 转义 s 中的 SQL 模式通配符。 */
{
$result = array();
foreach(str_split($s) as $ch)
{
if ($ch == "\\" || $ch == "%" || $ch == "_")
{
$result[] = "\\";
} /*if*/
$result[] = $ch;
} /*foreach*/
return
implode("", $result);
} /*escape_sql_wild*/
To Top