Codeigniter存入MySQL的转义字符未自动还原问题求助
首先要明确一个核心关键点:你直接执行SELECT 'Altaf\'s Journey'能得到正常结果,是因为数据库会解析SQL语句里的转义符;但从表中读取时显示带转义符的字符串,说明数据库中实际存储的就是Altaf\'s Journey(带转义反斜杠),而不是原始的Altaf's Journey。问题根源在数据存入环节,而非读取环节。
下面是最可能的几个原因和对应的解决办法:
1. 双重转义导致存储了多余的转义符
CodeIgniter的数据库类(不管是用Active Record还是直接调用$this->db->query())已经会自动对输入数据做SQL转义处理。如果你手动调用了$this->db->escape_str()再把数据传入,就会触发双重转义:
- 第一次手动转义:
escape_str("Altaf's Journey")得到Altaf\'s Journey - 第二次框架自动转义:会把反斜杠
\转义为\\,单引号'转义为\',最终SQL里的字符串变成Altaf\\'s Journey - 数据库执行INSERT时,会把
\\解析成\,\'解析成',所以最终存到表里的就是Altaf\'s Journey
举个错误示例:
// 错误:手动转义 + 框架自动转义 = 双重转义 $title = "Altaf's Journey"; $escaped_title = $this->db->escape_str($title); $this->db->insert('journeys', ['title' => $escaped_title]);
正确做法:完全不用手动调用escape_str(),直接把原始数据传给框架,它会自动处理转义:
$title = "Altaf's Journey"; $this->db->insert('journeys', ['title' => $title]);
如果是手动构造SQL语句,建议用$this->db->escape()(它会自动添加单引号并正确转义),而不是escape_str():
$title = "Altaf's Journey"; $escaped_title = $this->db->escape($title); $sql = "INSERT INTO journeys (title) VALUES ($escaped_title)"; $this->db->query($sql);
escape_str()只转义字符串但不添加引号,手动加引号很容易出错;escape()则会帮你处理所有细节,更安全可靠。
2. 魔术引号(Magic Quotes)开启导致自动转义
虽然PHP 5.4及以上版本已经移除了魔术引号,但如果你的服务器环境还开启了magic_quotes_gpc,用户提交的POST/GET数据会被自动添加转义符。这时候你再调用escape_str(),就会造成双重转义,最终存储带转义符的字符串。
你可以用下面的代码检查是否开启了魔术引号:
var_dump(get_magic_quotes_gpc());
如果返回true,建议:
- 优先在php.ini中关闭魔术引号:设置
magic_quotes_gpc = Off - 若无法修改php.ini,可在项目入口文件中添加代码反转义:
if (get_magic_quotes_gpc()) { function stripslashes_deep($value) { $value = is_array($value) ? array_map('stripslashes_deep', $value) : stripslashes($value); return $value; } $_POST = array_map('stripslashes_deep', $_POST); $_GET = array_map('stripslashes_deep', $_GET); $_COOKIE = array_map('stripslashes_deep', $_COOKIE); }
3. 数据库连接配置异常
检查CodeIgniter的数据库配置文件(application/config/database.php),确保字符集和相关设置正确:
$db['default']['char_set'] = 'utf8'; $db['default']['dbcollat'] = 'utf8_general_ci'; $db['default']['db_debug'] = TRUE; // 开启调试可以看到实际执行的SQL,方便排查
如果字符集设置不正确,可能导致转义逻辑异常,使得转义符被当作普通字符存储。
快速验证方法
开启数据库调试模式后,执行插入操作,查看框架输出的SQL语句:
如果看到类似INSERT INTO journeys (title) VALUES ('Altaf\\'s Journey'),那就实锤是双重转义的问题,去掉手动的escape_str()调用即可解决。
内容的提问来源于stack exchange,提问作者Mohammed Altaf

