上一篇:正则表达式中零宽断言?=和?!的区别(2019-06-22 23:02:19)
文章大纲

Mysql保存反斜杠莫名消失的问题

2019-06-23 17:04:07

昨晚写了一篇正则表达式相关的文章,修改保存后,文章里的\d表达式里的反斜杠就不见了。就因为这个坑,踩了一个通宵。


之前根本就不太熟悉stripslash、addslash、htmlspecialchars_decode这些函数的详细工作,所以代码有点乱,已经不知道当初是咋写的了。


但是可以先贴出我的项目model底层代码关于这段的实现:

protected function parseValue($value) {
if(is_string($value) || is_numeric($value)) {
$value = '\''.$this->escapeString($value).'\'';
}elseif(isset($value[0]) && is_string($value[0]) && strtolower($value[0]) == 'exp'){
$value = $value[1];
}elseif(is_array($value)) {
$value = array_map(array($this, 'parseValue'),$value);
}elseif(is_null($value)){
$value = 'NULL';
}
return $value;
}

public function escapeString($str) {
$str = addslashes(stripslashes($str));
return $str;
}

在更新和插入mysql表的数据时,每一列都会经历上面代码块里的parseValue方法,如果是字符串或数字,继而又会走escapeString方法。

我踩的坑就在这里的escapeString方法上。


我去手册先查了下addSlashes方法,是像下面这样描述的:

Returns a string with backslashes added before characters that need to be escaped. These characters are:

  • single quote (')
  • double quote (")
  • backslash (\)
  • NUL (the NUL byte)
  • 翻译过来就是:给需要转义的符号加上反斜杠然后返回,其中符号就只有单引号、双引号、反斜杠、空字节这四种。
  • stripslashes则只是做了相反的操作。

我用的是summernote富文本编辑器,所以一开始我在编辑器里保存\d正则表达式时,上面escapeString代码就已经先把我的这个反斜杠符号用stripslashes方法给去掉了,后面再怎么加addSlashes也不能让反斜杠再现了。

那就干脆直接删掉escapeString方法?
这时一旦文章里有单引号,就会导致sql语句错误,所以这里addSlashes是可以为文章里的单双引保驾护航的。
//没有给单引转义,这个sql语句就无法执行
insert into blog(content) values('我是一枚不折不扣的'码农'');

那就把stripSlashes方法去掉好啦?
这样子我本来只要显示一个反斜杠,保存到db里结果成了两个,除非在取数据时,再stripSlashes一次。
当然这里,stripSlashes方法还有删除无用的转义符,重新转义,确保数据格式更加安全。

我的最终解决方案:
public function escapeString($str) {
//就只加了下面这行代码
$str = str_ireplace("\\", "\", $str );
$str = addslashes(stripslashes($str));
return $str;
}
经过实践,发现数据取出来时,它会自动显示为反斜杠,无需我们再次将’\‘这部分再替换回去。

试了下面一段PHP代码:
$str = '\你好\\"我是一枚不折\不扣的码农\\\\';     
var_dump(htmlspecialchars_decode($str));
结果:
string(50) "\你好\"我是一枚不折\不扣的码农\\"
可以看到092这部分根本没变,看来浏览器会自动识别ASCII码对应的字符吧,htmlspecialchars_decode反而无能为力。
(这里结果可以看出,decode其实就是去掉转义字符,双引号前的反斜杠和两个反斜杠前各自的反斜杠,单个斜杠是原本字符,则保持不变)

一开始我在存数据前,还用了htmlspecialchars方法,然后取出数据的时候再用htmlspecialchars_decode来解析显示到网页,现在看来,不仅多此一举,还给自己带来了不必要的其它坑。
什么坑,就是用htmlspecialchars_decode方法时,会将我文章里的html代码也给解析了,如下:
//这块本来是代码,结果被一同解析显示成文本和图片在文章里了
$str = '<a class="link" href="http://www.zhai14.com">翟码农</a>
<img src="http://www.zhai14.com/media/upload/article/9671d518gy1g14y4dwe36j20ki08u758.jpg">';

现在对比一下我的mysql db存储文章的格式变化,提升经验。
踩坑前:
明天就要星期一啦!&lt;br /&gt;
明天就要星期一啦!!&lt;br /&gt;
明天就要星期一啦!!!&lt;br /&gt;
蹭了一天饭躺了一天床的我,实在愧于向大家打鸡血。&lt;br /&gt;
可是星期一也是属于每一个人的,我也需要给自己注射注射一下子。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
修复后:
明天就要星期一啦!<br /> 
明天就要星期一啦!!<br />
明天就要星期一啦!!!<br />
蹭了一天饭躺了一天床的我,实在愧于向大家打鸡血。<br />
可是星期一也是属于每一个人的,我也需要给自己注射注射一下子。<br /> <br /> <br />

综上看下来,其实存取文章数据这块,很简单,就留意下反斜杠的替换,其它我们无需再做额外的工作了。

上一篇:正则表达式中零宽断言?=和?!的区别(2019-06-22 23:02:19)
我要评论
评论列表