Heim  >  Artikel  >  Backend-Entwicklung  >  php中的mysqli_set_charset和SET NAMES优劣分析

php中的mysqli_set_charset和SET NAMES优劣分析

WBOY
WBOYOriginal
2016-07-25 09:03:071098Durchsuche
  1. //php-5.2.11-SRC/ext/mysqli/mysqli_nonapi.c line 342
  2. PHP_FUNCTION(mysqli_set_charset)
  3. {
  4. MY_MYSQL*mysql;
  5. zval*mysql_link;
  6. char *cs_name = NULL;
  7. unsigned int len;
  8. if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis()
  9. , "Os", &mysql_link, mysqli_link_class_entry, &cs_name, &len) == FAILURE) {
  10. return;
  11. }
  12. MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL*, &mysql_link, "mysqli_link"
  13. , MYSQLI_STATUS_VALID);
  14. if (mysql_set_character_set(mysql->mysql, cs_name)) {
  15. //** 调用libmysql的对应函数
  16. RETURN_FALSE;
  17. }
  18. RETURN_TRUE;
  19. }
  20. ?>
复制代码

那mysql_set_character_set又做了什么呢?

  1. //mysql-5.1.30-SRC/libmysql/client.c, line 3166:
  2. int STDCALLmysql_set_character_set(MYSQL*mysql, const char *cs_name)
  3. {
  4. structcharset_info_st *cs;
  5. const char *save_csdir= charsets_dir;
  6. if (mysql->options.charset_dir)
  7. charsets_dir= mysql->options.charset_dir;
  8. if (strlen(cs_name) (cs= get_charset_by_csname(cs_name, MY_CS_PRIMARY, MYF(0))))
  9. {
  10. char buff[MY_CS_NAME_SIZE + 10];
  11. charsets_dir= save_csdir;
  12. /* Skip execution of "SET NAMES" for pre-4.1 servers */
  13. if (mysql_get_server_version(mysql) return 0;
  14. sprintf(buff, "SET NAMES %s", cs_name);
  15. if (!mysql_real_query(mysql, buff, strlen(buff)))
  16. {
  17. mysql->charset= cs;
  18. }
  19. }
  20. //以下省略
  21. ?>
复制代码

我们可以看到, mysqli_set_charset除了做了”SET NAMES”以外, 还多做了一步:

  1. sprintf(buff, "SET NAMES %s", cs_name);
  2. if (!mysql_real_query(mysql, buff, strlen(buff)))
  3. {
  4. mysql->charset= cs;
  5. }
  6. ?>
复制代码

而对于mysql这个核心结构的成员charset又有什么作用呢?

这就要说说mysql_real_escape_string()了, 这个函数和mysql_escape_string的区别就是, 它会考虑”当前”字符集. 那么这个当前字符集从哪里来呢?

对了, 你猜的没错, 就是mysql->charset.

mysql_real_string在判断宽字符集的字符的时候, 就根据这个成员变量来分别采用不同的策略, 比如如果是utf-8, 那么就会采用libmysql/ctype-utf8.c.

看个实例, 默认mysql连接字符集是latin-1, (经典的5c问题):

  1. $db = mysql_connect('localhost:3737', 'root' ,'123456');
  2. mysql_select_db("test");
  3. $a = "\x91\x5c";//"慭"的gbk编码, 低字节为5c, 也就是ascii中的"\"
  4. var_dump(addslashes($a));
  5. var_dump(mysql_real_escape_string($a, $db));
  6. mysql_query("set names gbk");
  7. var_dump(mysql_real_escape_string($a, $db));
  8. mysql_set_charset("gbk");
  9. var_dump(mysql_real_escape_string($a, $db));
  10. ?>
复制代码

因为, “慭”的gbk编码低字节为5c, 也就是ascii中的”\”, 而因为除了mysql(i)_set_charset影响mysql->charset以外, 其他时刻mysql->charset都为默认值, 所以, 结果就是: $ php -f 5c.php string(3) "慭\" string(3) "慭\" string(3) "慭\" string(2) "慭"

本文转自:http://www.laruence.com/2010/04/12/1396.html



Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn