当有“ñ”字母时,带有火鸟的 PDO 会抛出“�”
PDO with firebird throws "�" when there is a "ñ" letter
我的table:
+--------+----------+
| U_COD | U_NAME |
+--------+----------+
| 01 | Daniel |
+--------+----------+
| 02 | Ñandu |
+--------+----------+
| 03 | Pañ |
+--------+----------+
我正在连接并像这样对我的 firebird 数据库进行简单查询:
$host = 'firebird:dbname=my/dir/db_test.gdb;charset=UTF8';
$password = 'mypass';
$username = 'myuname';
try{
$db = new PDO($host, $username, $password);
$db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
}catch(PDOException $e){
echo "Failed: " . $e->getMessage();
}
$getData=$db->prepare("SELECT * FROM T_TEST ORDER BY U_NAME ASC");
$getData->execute();
$arrData=$getData->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($arrData);
但是当我运行文件时,我的数据库中所有包含一些“ñ”字母的值都显示为空,像这样:
[
{"U_COD":"01","U_NAME":"Daniel"},
{"U_COD":"02","U_NAME":null},
{"U_COD":"03","U_NAME":null}
]
我想知道我做错了什么,如果您需要我的 firebird 数据库中的任何其他详细信息,请告诉我。
编辑
a var_dump($arrData)
显示值,但在应该有“ñ”字母时带有“�”:
array(3) {
[0]=>
array(2) {
["U_COD"]=>
string(2) "01"
["U_NAME"]=>
string(6) "Daniel"
},
array(2) {
["U_COD"]=>
string(2) "02"
["U_NAME"]=>
string(5) "�andu"
},
array(2) {
["U_COD"]=>
string(2) "03"
["U_NAME"]=>
string(3) "Pa�"
}
}
问题是该列的字符集是 NONE
,并且该列中存储的字节(例如,它是使用 WIN1252 等编码存储的)和您的字节之间可能不匹配连接字符集 (UTF8)。鉴于源列没有明确的字符集,Firebird 无法将字符音译为连接字符集,而是按原样发送字节,ñ
的字节在 UTF8 中无效,因此 PHP 将其替换为 unicode 替换字符。
作为短期解决方案,您可以尝试明确指定正确的连接字符集(例如 WIN1252)或明确强制转换列(例如 cast(U_NAME as varchar(100) character set win1252)
),但对于长期解决方案,您需要确保使用明确的字符集定义列。在您当前的设置中,如果您 write 来自多个应用程序的数据,每个应用程序都使用自己的隐式或显式连接字符集(例如,一个应用程序使用 WIN1252 写入,另一个应用程序使用UTF8,然后 - 如果列没有明确的字符集 - 一个人无法正确读取另一个人写入的数据)。
我的table:
+--------+----------+
| U_COD | U_NAME |
+--------+----------+
| 01 | Daniel |
+--------+----------+
| 02 | Ñandu |
+--------+----------+
| 03 | Pañ |
+--------+----------+
我正在连接并像这样对我的 firebird 数据库进行简单查询:
$host = 'firebird:dbname=my/dir/db_test.gdb;charset=UTF8';
$password = 'mypass';
$username = 'myuname';
try{
$db = new PDO($host, $username, $password);
$db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
}catch(PDOException $e){
echo "Failed: " . $e->getMessage();
}
$getData=$db->prepare("SELECT * FROM T_TEST ORDER BY U_NAME ASC");
$getData->execute();
$arrData=$getData->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($arrData);
但是当我运行文件时,我的数据库中所有包含一些“ñ”字母的值都显示为空,像这样:
[
{"U_COD":"01","U_NAME":"Daniel"},
{"U_COD":"02","U_NAME":null},
{"U_COD":"03","U_NAME":null}
]
我想知道我做错了什么,如果您需要我的 firebird 数据库中的任何其他详细信息,请告诉我。
编辑
a var_dump($arrData)
显示值,但在应该有“ñ”字母时带有“�”:
array(3) {
[0]=>
array(2) {
["U_COD"]=>
string(2) "01"
["U_NAME"]=>
string(6) "Daniel"
},
array(2) {
["U_COD"]=>
string(2) "02"
["U_NAME"]=>
string(5) "�andu"
},
array(2) {
["U_COD"]=>
string(2) "03"
["U_NAME"]=>
string(3) "Pa�"
}
}
问题是该列的字符集是 NONE
,并且该列中存储的字节(例如,它是使用 WIN1252 等编码存储的)和您的字节之间可能不匹配连接字符集 (UTF8)。鉴于源列没有明确的字符集,Firebird 无法将字符音译为连接字符集,而是按原样发送字节,ñ
的字节在 UTF8 中无效,因此 PHP 将其替换为 unicode 替换字符。
作为短期解决方案,您可以尝试明确指定正确的连接字符集(例如 WIN1252)或明确强制转换列(例如 cast(U_NAME as varchar(100) character set win1252)
),但对于长期解决方案,您需要确保使用明确的字符集定义列。在您当前的设置中,如果您 write 来自多个应用程序的数据,每个应用程序都使用自己的隐式或显式连接字符集(例如,一个应用程序使用 WIN1252 写入,另一个应用程序使用UTF8,然后 - 如果列没有明确的字符集 - 一个人无法正确读取另一个人写入的数据)。