我很惊讶我无法通过搜索找到这个问题的简单答案。
我在PHP中有一个用户输入的Web应用程序。由于应用程序的性质,用户可能经常使用扩展的ASCII字符(例如“ALT代码”)。
我目前的具体问题是使用ALT代码26,这是一个右箭头(→)。这将伴随其他文本存储在同一字段中(例如,'this→that'
)。
我的列类型是NVARCHAR。
这是我尝试过的:
我尝试过不进行转换,只是按正常方式插入值,但该值存储为thisâ??that
。
我尝试使用iconv('UTF-8', 'UCS-2', $value)
将值转换为PHP中的UCS-2,但我收到错误Unclosed quotation mark after the character string 't'.
。查询最终看起来像这样:UPDATE myTable SET myColumn = 'this�!that'
。
我已尝试进行上述转换,然后在引用值之前添加N,但我收到相同的错误消息。查询如下所示:UPDATE myTable SET myColumn = N'this�!that'
。
我尝试删除UCS-2转换,只是在引用值之前添加N,然后查询再次生效,但该值存储为thisâ that
。
我已尝试在PHP中使用utf8_decode($value)
,但箭头只是替换为问号。
所以任何人都可以回答(看似简单的)问题,如何将这个值存储在我的数据库中,然后按照最初输入的方式检索它?
我正在使用PHP 5.5和MSSQL 2012.如果驱动程序/操作系统版本的任何问题发挥作用,它是通过FreeTDS连接的Linux服务器。没有可能改变这一点。
答案 0 :(得分:5)
您可以尝试对输入进行base64编码,使用PHP base64_encode()
和base64_decode()
来处理这一点非常简单,它应该可以处理用户扔过它的内容。
(编辑:您显然也可以执行base64 encoding on the SQL Server side。这似乎不应该对imho负责,但它是一个选项。)
答案 1 :(得分:1)
好像你的freetds.conf
错了。您需要TDS协议版本> = 7.0才能支持unicode。 See this for more details
修改您的freetds.conf
:
[global]
# TDS protocol version
tds version = 7.4
client charset = UTF-8
还要确保配置PHP正确:
ini_set('mssql.charset', 'UTF-8');
答案 2 :(得分:1)
看起来你有this→!that
,UTF-8编码this→!that
的ASCII副本。
在这里提出的建议之后把事情做好,并不能神奇地解决所有问题。特别是如果您的表格中已经存在数据损坏的话。
你需要重新开始寻找正确的道路。
TestTable(Column1)
test.php
freetds.conf
中,明确地在client charset = UTF-8
或[global]
部分下添加设置[WhateverYourServerNameIs]
。这是在FreeTDS和SQL Server之间进行通信时使用的字符集。<强> test.php的强>:
<?php
// character set to be used in response
header('Content-Type: text/plain; charset=utf-8');
// charset to be used in communication between PHP driver and FreeTDS.
ini_set('mssql.charset', 'UTF-8');
// make the connection
$conn = mssql_connect("ServerNameSpecifiedInFreetdsDotConf", "username", "passw0rd");
// select database
mssql_select_db("DatabaseName", $conn);
// insert something immediately
// do not forget to use the N prefix, may cause problems with mssql_query if omitted
$insertQuery = mssql_query("Insert Into TestTable(Column1) Select N'this→that';", $conn);
// list all the records
$query = mssql_query( "Select * From TestTable", $conn );
while ($row = mssql_fetch_array($query))
echo $row["Column1"].PHP_EOL;
mssql_close($conn); // close the connection
?>
反复运行test.php
,看看会发生什么。如果您在PHP响应和SQL Server Management Studio上看到this→that
,则意味着您已全部设置。
如果您仍然得到意想不到的结果,请告诉我们。
答案 3 :(得分:1)
接受的答案似乎可以胜任;是的,您可以将其编码为base64
,然后再将其解码,但随后所有使用该远程数据库的应用程序都应更改并支持要base64
编码的字段。我的想法是,如果有一个远程MS SQL Server数据库,可能有其他应用程序(或多个应用程序)可能会使用它,因此必须更改应用程序以支持普通和base64
编码。而且您还必须同时处理纯文本和base64
转换后的文本。
我搜索了一下,我发现如何使用MS SQL命令和PHP将UNICODE文本发送到MS SQL Server,以将UNICODE字节转换为HEX数字。
如果你查看mssql_fetch_array
(http://php.net/manual/ru/function.mssql-fetch-array.php#80076)的PHP文档,你会在评论中看到一个非常好的解决方案,将文本转换为UNICODE HEX值然后发送HEX数据直接发送到MS SQL Server,如下所示:
将Unicode文本转换为HEX数据
// sending data to database
$utf8 = 'Δοκιμή με unicode → Test with Unicode'; // some Greek text for example
$ucs2 = iconv('UTF-8', 'UCS-2LE', $utf8);
// converting UCS-2 string into "binary" hexadecimal form
$arr = unpack('H*hex', $ucs2);
$hex = "0x{$arr['hex']}";
// IMPORTANT!
// please note that value must be passed without apostrophes
// it should be "... values(0x0123456789ABCEF) ...", not "... values('0x0123456789ABCEF') ..."
mssql_query("INSERT INTO mytable (myfield) VALUES ({$hex})", $link);
现在所有文本实际上都以UNICODE的形式正确地存储到NVARCHAR
数据库字段,并且您只需要将其作为纯文本发送和存储而不是编码。
要检索该文本,您需要让MS SQL Server发送回UNICODE编码的文本,如下所示:
从MS SQL Server检索Unicode文本
// retrieving data from database
// IMPORTANT!
// please note that "varbinary" expects number of bytes
// in this example it must be 200 (bytes), while size of field is 100 (UCS-2 chars)
// myfield is of 50 length, so I set VARBINARY to 100
$result = mssql_query("SELECT CONVERT(VARBINARY(100), myfield) AS myfield FROM mytable", $link);
while (($row = mssql_fetch_array($result, MSSQL_BOTH)))
{
// we get data in UCS-2
// I use UTF-8 in my project, so I encode it back
echo '1. '.iconv('UCS-2LE', 'UTF-8', $row['myfield'])).PHP_EOL;
// or you can even use mb_convert_encoding to convert from UCS-2LE to UTF-8
echo '2. '.mb_convert_encoding($row['myfield'], 'UTF-8', 'UCS-2LE').PHP_EOL;
}
INSERT后带有UNICODE数据的MS SQL表
使用PHP页面显示值的输出结果
我不确定您是否可以在此处访问我的测试页,但您可以尝试查看实时结果: http://dbg.deve.wiznet.gr/php56/mssql/test1.php