strtolower 和 mb_strtolower 的区别

4月13日。

昨天发现在执行搜索的时候,如果搜索关键词带有如 ãé 这样的字符的时候会报错。

起初以为是solr和tomcat配置的问题,但是检查发现tomcat配置的编码是utf8是没问题。而且正式服务器上并不会有问题。

另外奇怪的是,使用的是同一个tomcat+solr的服务器,在3个环境(测试+开发)下是不一样的:

A: centos=6.5, php=5.4.16
B: windows=7, php=5.4.12
C: osx=10.11, php=5.5.33

只有B下面不会报错。

经过B和C下两台电脑的调试,发现传给solr时候的关键词对于 ãé 字符的编码并不一样,原来是在这里对搜索字符串做了 strtolower 导致。测试信息如下:

$foo = 'This is é';
pr('Normal: '.$foo);    // Normal: This is é
pr('After strtolower: '.strtolower($foo));    // After strtolower: this is �

导致传给solr的字符串带有无法解析utf8的乱码,tomcat报错:Invalid character encoding detected after position 482 of query string / form data (while parsing as UTF-8)

解决办法是把strtolower换成mb_strtolower

$foo = 'This is é';
pr('Normal: '.$foo);    // Normal: This is é
pr('After strtolower: '.strtolower($foo));    // After strtolower: this is �
pr('After mb_strtolower: '.mb_strtolower($foo));    // After mb_strtolower: this is é

问题解决。

PHP手册对于mb_strtolower的解释:

string mb_strtolower ( string $str [, string $encoding = mb_internal_encoding() ] )

Returns str with all alphabetic characters converted to lowercase.

str
    The string being lowercased.
encoding
    The encoding parameter is the character encoding. If it is omitted, the internal character encoding value will be used.
    
By contrast to strtolower(), 'alphabetic' is determined by the Unicode character properties. Thus the behaviour of this function is not affected by locale settings and it can convert any characters that have 'alphabetic' property, such as A-umlaut (Ä).

至于为什么正式服务器和B电脑不会有这个问题,悬而未决,等后面找到再补充吧 :(

完。