クエスト
アクセント付き文字を含む行をフェッチしようとしています。列(NAME
)のエンコーディングは_latin1_swedish_ci
_です。
コード
次のクエリは、phpMyAdminを使用して_Abord â Plouffe
_を返します。
_SELECT C.NAME FROM CITY C
WHERE C.REGION_ID=10 AND C.NAME_LOWERCASE LIKE '%abor%'
ORDER BY C.NAME LIMIT 30
_
以下は期待値を表示します(関数はdb_fetch_all( $result )
と呼ばれます):
_ while( $row = mysql_fetch_assoc( $result ) ) {
foreach( $row as $value ) {
echo $value . " ";
$value = utf8_encode( $value );
echo $value . " ";
}
$r[] = $row;
}
_
表示される値:_5482 5482 Abord â Plouffe Abord â Plouffe
_
次に、配列は_json_encode
_を使用してエンコードされます。
_$rows = db_fetch_all( $result );
echo json_encode( $rows );
_
問題
Webブラウザーは次の値を受け取ります。
_{"ID":"5482","NAME":null}
_
の代わりに:
_{"ID":"5482","NAME":"Abord â Plouffe"}
_
(またはエンコードされた同等のもの。)
質問
ドキュメントには、json_encode()
がUTF-8で機能することが記載されています。 LATIN1からUTF-8にエンコードされている値を確認できます。ただし、json_encode()
の呼び出し後、値はnull
になります。
json_encode()
でUTF-8値を適切にエンコードするにはどうすればよいですか?
可能な解決策の1つは Zend Framework を使用することですが、回避できればいいのではないでしょうか。
// Create an empty array for the encoded resultset
$rows = array();
// Loop over the db resultset and put encoded values into $rows
while($row = mysql_fetch_assoc($result)) {
$rows[] = array_map('utf8_encode', $row);
}
// Output $rows
echo json_encode($rows);
foreach( $row as $value ) {
$value = utf8_encode( $value );
エンコードされた値を実際に$row
配列に書き戻すのではなく、ローカル変数$value
を変更するだけです。変数を変更したときに書き戻したい場合は、参照として扱う必要があります。
foreach( $row as &$value ) {
個人的には、可能な限り参照を避けようとしますが、この場合は、代わりにKemoが投稿したarray_map
を使用します。
または、アプリをUTF-8に移行するための最初のステップとして、mysql_set_charset
をUTF-8に変換して、実際のテーブル照合に関係なく、UTF-8で戻り値を取得します。
私の解決策は、SELECT
の前にこの行mysql_query('SET CHARACTER SET utf8');
を挿入することです。この方法は良いです。
それをクエリに置くのではなく、次のように置くべきです:
mysql_set_charset('utf8');
mysql connectステートメントの後。
接続:mysql_set_charset('utf8', $link);
例:
<?php
$link = mysql_connect('localhost', 'your_user', 'your_password');
mysql_set_charset('utf8', $link);
$db_selected = mysql_select_db('your_db', $link);
...
それが多少役立つことを願っています。
結果をiconv_r($row,"LATIN1","UTF-8//TRANSLIT");
する前にjson_encode()
(以下の関数)を試してください。
テーブルエンコーディングと結果セットエンコーディングとしてUTF-8を使用していますが、フォームを介してUTF-8以外の文字を送信することもでき、すべての入力ソースを追跡するのが面倒なので、json_encode()
より安全にするため。特に、英国の人々がとても気に入っているように見える度合記号と「スマートクオート」を含むNULL文字列を私はそれに持っていました。
function safe_json_encode($mixed,$missing="TRANSLIT"){
$out=json_encode($mixed);
if ($err= json_last_error()){
iconv_r("UTF-8","UTF-8//$missing",$mixed);
$out=json_encode($mixed);
}
return $out;
}
function iconv_r($charset_i, $charset_o, &$mixed) {
if (is_string($mixed)) {
$mixed = iconv($charset_i, $charset_o, $mixed);
} else {
if (is_object($mixed)){
$mixed = (array) $mixed;
}
if (is_array($mixed)){
foreach ($mixed as $key => &$value) {
iconv_r($charset_i, $charset_o, $value);
}
}
}
}