最近、同社は PHP セキュリティ プログラミング トレーニングを開催しました。これには、Mysql の "SET NAMES" および mysql_set_charset (mysqli_set_charset) に関する内容が含まれていました:
そういえば、"SET NAMES" の代わりに mysqli_set_charset (mysqli:set_charset) を使用してみてください。この内容は PHP マニュアルにも記載されていますが、その理由は説明されていません
最近、何人かの友人が私にこの質問をしました。なぜですか? 質問する人がたくさんいるので、ブログを書こうと思いました。この部分を具体的に紹介します。
まず、多くの人は「SET NAMES」が何をするのか知りません。
私の前回の記事では、MySQL の 3 つの「character_set_client/character_set_connection/character_set_results」環境変数について詳しく説明しました。 " については、ここで簡単に紹介します。
これら 3 つの変数は、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_MY SQL*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) = = 失敗) {
reターン;
}
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;
}
コードをコピーします
コードは次のとおりです:
//私のSQL-5.1.30 -SRC/libmysql/client.c、行 3166:
int STDCALLmysql_set_character_set(MYSQL*mysql, const char *cs_name)
{
structcharset_info_st *cs;
const char *save_csdir= charsets_dir;オプション .charset_dir )
charsets_dir = mysql->options.charset_dir; if (strlen(cs_name) < MY_CS_NAME_SIZE && (cs= get_charset_by_csname(cs_name, MY_CS_PRIMARY, MYF(0)))) { char buff[MY_CS_NAME_SIZE + 10] ;
charsets_dir = save_csdir
/* 4.1 より前のサーバーの場合は「SET NAMES」の実行をスキップします。 */
の場合 ( mysql_get_server_version(mysql) < 40100)
sprintf(buff, "SET NAMES %s", cs_name);
if (!mysql_real_query(mysql, buff, strlen(buff)); charset= cs;
}
}
//以下は省略されています
「SET NAMES」に加えて、mysqli_set_charset がもう 1 つのステップも実行していることがわかります:
コードをコピーします
コードは次のとおりです以下:
sprintf(buff , "SET NAMES %s", cs_name);
if (!mysql_real_query(mysql, buff, strlen(buff)))
{
mysql->charset= cs;
mysql のコア構造について メンバー charset の役割は何ですか?
この関数と mysql_escape_string の違いは、「現在の」文字セットを考慮するということです。文字セットの由来は?
はい、ご想像のとおり、mysql->charset です。たとえば、ワイド文字セットの文字を判断する場合、mysql_real_string はこのメンバー変数に基づいてさまざまな戦略を使用します。 8 の場合、libmysql/ctype-utf8.c が使用されます。
例を見てください。デフォルトの mysql 接続文字セットは latin-1 です (古典的な 5c の問題): コードをコピーします
コードは次のとおりです。以下:
$ db = mysql_connect('localhost:3737', 'root' ,'123456');
$a = "x91x5c";// 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");
なぜなら、「慭」の下位バイトの gbk エンコードは 5c (ascii では「」) であり、mysql->charset に影響を与える mysql(i)_set_charset を除いて、mysql->charset は他のバージョンのデフォルト値であるからです。
コードをコピーします コードは次のとおりです:
$ php -f 5c.php
string(3) ""
string(3) ""
string (3) " "
string(2) "慭"もう皆さんには分かりましたか?
http://www.bkjia.com/PHPjc/326354.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/326354.html技術記事最近、同社は PHP セキュリティ プログラミング トレーニングを開催しました。これには、Mysql の「SET NAMES」と mysql_set_charset (mysqli_set_charset) に関する内容が含まれていました。そういえば、mysqli を使ってみてください...