Rumah pembangunan bahagian belakang tutorial php mysqli_set_charset和SET NAMES使用抉择及优劣分析_PHP

mysqli_set_charset和SET NAMES使用抉择及优劣分析_PHP

Jun 01, 2016 pm 12:08 PM
charset set

最近公司组织了个PHP安全编程的培训, 其中涉及到一部分关于Mysql的”SET NAMES”和mysql_set_charset (mysqli_set_charset)的内容:
说到, 尽量使用mysqli_set_charset(mysqli:set_charset)而不是”SET NAMES”, 当然, 这个内容在PHP手册中也有叙及, 但是却没有解释为什么.

最近有好几个朋友问我这个问题, 到底为什么?
问的人多了, 我也就觉得可以写篇blog, 专门介绍下这部分的内容了.
首先, 很多人都不知道”SET NAMES”到底是做了什么,
我之前的文章深入MySQL字符集设置中, 曾经介绍过character_set_client/character_set_connection/character_set_results这三个MySQL的”环境变量”, 这里再简单介绍下,
这三个变量, 分别告诉MySQL服务器, 客户端的编码集, 在传输给MySQL服务器的时候的编码集, 以及期望MySQL返回的结果的编码集.
比如, 通过使用”SET NAMES utf8″, 就告诉服务器, 我用的是utf-8编码, 我希望你也给我返回utf-8编码的查询结果.

一般情况下, 使用”SET NAMES”就足够了, 也是可以保证正确的. 那么为什么手册又要说推荐使用mysqli_set_charset(PHP>=5.0.5)呢?
首先, 我们看看mysqli_set_charset到底做了什么(注意星号注释处, mysql_set_charset类似):
复制代码 代码如下:
//php-5.2.11-SRC/ext/mysqli/mysqli_nonapi.c line 342
PHP_FUNCTION(mysqli_set_charset)
{
MY_MYSQL*mysql;
zval*mysql_link;
char *cs_name = NULL;
unsigned int len;
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis()
, "Os", &mysql_link, mysqli_link_class_entry, &cs_name, &len) == FAILURE) {
return;
}
MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL*, &mysql_link, "mysqli_link"
, MYSQLI_STATUS_VALID);
if (mysql_set_character_set(mysql->mysql, cs_name)) {
//** 调用libmysql的对应函数
RETURN_FALSE;
}
RETURN_TRUE;
}

那mysql_set_character_set又做了什么呢?
复制代码 代码如下:
//mysql-5.1.30-SRC/libmysql/client.c, line 3166:
int STDCALLmysql_set_character_set(MYSQL*mysql, const char *cs_name)
{
structcharset_info_st *cs;
const char *save_csdir= charsets_dir;
if (mysql->options.charset_dir)
charsets_dir= mysql->options.charset_dir;
if (strlen(cs_name) (cs= get_charset_by_csname(cs_name, MY_CS_PRIMARY, MYF(0))))
{
char buff[MY_CS_NAME_SIZE + 10];
charsets_dir= save_csdir;
/* Skip execution of "SET NAMES" for pre-4.1 servers */
if (mysql_get_server_version(mysql) return 0;
sprintf(buff, "SET NAMES %s", cs_name);
if (!mysql_real_query(mysql, buff, strlen(buff)))
{
mysql->charset= cs;
}
}
//以下省略

我们可以看到, mysqli_set_charset除了做了”SET NAMES”以外, 还多做了一步:
复制代码 代码如下:
sprintf(buff, "SET NAMES %s", cs_name);
if (!mysql_real_query(mysql, buff, strlen(buff)))
{
mysql->charset= cs;
}

而对于mysql这个核心结构的成员charset又有什么作用呢?
这就要说说mysql_real_escape_string()了, 这个函数和mysql_escape_string的区别就是, 它会考虑”当前”字符集. 那么这个当前字符集从哪里来呢?
对了, 你猜的没错, 就是mysql->charset.
mysql_real_string在判断宽字符集的字符的时候, 就根据这个成员变量来分别采用不同的策略, 比如如果是utf-8, 那么就会采用libmysql/ctype-utf8.c.
看个实例, 默认mysql连接字符集是latin-1, (经典的5c问题):
复制代码 代码如下:
$db = mysql_connect('localhost:3737', 'root' ,'123456');
mysql_select_db("test");
$a = "\x91\x5c";//"慭"的gbk编码, 低字节为5c, 也就是ascii中的"\"
var_dump(addslashes($a));
var_dump(mysql_real_escape_string($a, $db));
mysql_query("set names gbk");
var_dump(mysql_real_escape_string($a, $db));
mysql_set_charset("gbk");
var_dump(mysql_real_escape_string($a, $db));
?>

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

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Artikel Panas

Repo: Cara menghidupkan semula rakan sepasukan
1 bulan yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Kristal tenaga dijelaskan dan apa yang mereka lakukan (kristal kuning)
2 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: Cara mendapatkan biji gergasi
4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Penjelasan terperinci tentang fungsi Set tag dalam teg SQL dinamik MyBatis Penjelasan terperinci tentang fungsi Set tag dalam teg SQL dinamik MyBatis Feb 26, 2024 pm 07:48 PM

Tafsiran teg SQL dinamik MyBatis: Penjelasan terperinci tentang penggunaan teg Set MyBatis ialah rangka kerja lapisan kegigihan yang sangat baik Ia menyediakan banyak teg SQL dinamik dan boleh membina pernyataan operasi pangkalan data secara fleksibel. Antaranya, tag Set ialah tag yang digunakan untuk menjana klausa SET dalam kenyataan UPDATE, yang sangat biasa digunakan dalam operasi kemas kini. Artikel ini akan menerangkan secara terperinci penggunaan teg Set dalam MyBatis dan menunjukkan kefungsiannya melalui contoh kod tertentu. Apakah itu Set tag Set tag digunakan dalam MyBati

Bagaimana untuk memadam elemen dari set dalam javascript Bagaimana untuk memadam elemen dari set dalam javascript Jan 12, 2022 am 10:56 AM

Kaedah untuk memadam elemen: 1. Gunakan delete() untuk memadam elemen yang ditentukan daripada objek Set, sintaks "setObj.delete(value);" 2. Gunakan clear() untuk memadam semua elemen dalam objek Set, sintaks "setObj.clear();".

Inventori penggunaan biasa dict dan set dalam pengaturcaraan Python Inventori penggunaan biasa dict dan set dalam pengaturcaraan Python Jul 25, 2023 pm 04:52 PM

Artikel ini berdasarkan asas Python dan memperkenalkan cara menggunakan dict dan set Dict menggunakan struktur storan nilai kunci sangat berguna dalam Python ialah rentetan.

Apakah perbezaan antara kaedah yang ditetapkan dan kaedah tambah dalam Senarai dalam java? Apakah perbezaan antara kaedah yang ditetapkan dan kaedah tambah dalam Senarai dalam java? Apr 19, 2023 pm 07:49 PM

Prakata Terdapat dua kaedah yang hampir sama dalam Senarai antara muka koleksi yang biasa digunakan dalam Java: Eset(intindex,Eelement);voidadd(intindex,Eelement); kedua-dua kaedah ini memasukkan elemen tertentu pada kedudukan tertentu dalam koleksi, kemudian Apakah perbezaannya antara dua kaedah ini? Seterusnya, mari kita lihat perbezaan dan persamaan antara kedua-dua kaedah ini melalui ArrayList, pelaksanaan koleksi yang biasa kita gunakan Pertama, mari kita lihat persamaan antara kedua-dua kaedah ini dalam ArrayList koleksi, seperti Contoh berikut: #Masukkan F pada kedudukan ke-2 koleksi #Masukkan Senarai Senarai= melalui kaedah tambah

Perbandingan Peta Java dan rangka kerja koleksi lain: analisis kelebihan dan kekurangan serta panduan senario aplikasi Perbandingan Peta Java dan rangka kerja koleksi lain: analisis kelebihan dan kekurangan serta panduan senario aplikasi Feb 19, 2024 pm 10:24 PM

1. Gambaran Keseluruhan Rangka Kerja Pengumpulan Peta Rangka kerja pengumpulan Peta ialah struktur data pasangan nilai kunci yang membolehkan anda menggunakan kunci untuk mencari dan menyimpan nilai. Setiap kunci dalam Peta adalah unik dan hanya boleh dikaitkan dengan satu nilai. Pelaksanaan biasa dalam rangka kerja pengumpulan Peta termasuk HashMap, TreeMap dan LinkedHashMap. 1.HashMapHashMap ialah pelaksanaan Peta yang paling banyak digunakan dalam Java Ia menyimpan data berdasarkan jadual cincang. HashMap mempunyai prestasi cemerlang, dan kerumitan masa operasi carian dan sisipan ialah O(1), tetapi ia tidak menjamin susunan unsur. Kod demo: Mapmap=newHashMap

Bagaimana untuk melaksanakan perintah Set bagi klien Tile bersepadu Springboot Bagaimana untuk melaksanakan perintah Set bagi klien Tile bersepadu Springboot May 19, 2023 pm 01:37 PM

Sintaks arahan yang ditetapkan SETkeyid[FIELDnamevalue...][EXseconds][NX|XX](OBJECTgeojson)|(POINTlatlonz)|(BOUNDSminlatminlonmaxlatmaxlon)|(HASHgeohash)|(STRINGvalue) Perintah yang ditetapkan adalah bersamaan dengan penggunaan perintah cincang dalam redis. Ia juga merupakan gabungan kunci dan id, tetapi perbezaannya ialah perintah set Tile38 juga boleh membawa lebih banyak atribut lain, seperti menyesuaikan medan FIELD, menetapkan tempoh sah EX, dll., maka kita perlu

Kegunaan biasa set Kegunaan biasa set Oct 24, 2023 am 11:25 AM

Kegunaan biasa set termasuk mencipta Set, menambah elemen, memadam elemen, menentukan sama ada Set kosong, mendapatkan saiz Set, melintasi Set, mencari elemen dan operasi set. Pengenalan terperinci: 1. Buat Set, Setset=newHashSet();; 2. Tambah elemen, set.add("java"); set.add("python");; 3. Padam elemen, set.remove("java");

Panduan Praktikal Rangka Kerja Koleksi Java: Ajar anda langkah demi langkah cara menggunakan rangka kerja dan menyelesaikan masalah praktikal Panduan Praktikal Rangka Kerja Koleksi Java: Ajar anda langkah demi langkah cara menggunakan rangka kerja dan menyelesaikan masalah praktikal Feb 23, 2024 am 10:52 AM

1.ListList ialah koleksi tertib dalam rangka kerja koleksi Java yang membenarkan elemen diulang dan elemen boleh diakses melalui indeks. Kelas pelaksanaan biasa Senarai termasuk ArrayList, LinkedList dan Vector. Berikut menunjukkan cara menggunakan ArrayList untuk menyimpan set integer: importjava.util.ArrayList;publicclassArrayListDemo{publicstaticvoidmain(String[]args){//Buat objek ArrayList ArrayListnumbers=newArr

See all articles