PHP PDO ODBC, похоже, не в состоянии хранить символы NVARCHAR (UTF-16) без некоторого ручного кодирования. Похоже, что это довольно распространенная «ошибка» во всем Интернете, и ни у кого, похоже, нет окончательного решения.
Как воспроизвести ошибку
こんにちは
(Значит привет)ã“ã‚“ã«ã¡ã¯
こんにちは
Это не так плохо, но и не хорошо. PHP работает, но когда у вас есть другие приложения, которые не в PHP и которые обращаются к этой информации из вашей базы данных, они получат неверную строку: ã“ã‚“ã«ã¡ã¯
,
В идеале вы хотели бы иметь こんにちは
везде.
Симптом
Кажется, что PDO не имеет никакого понятия о NVARCHAR, то есть символах, которые кодируются с использованием 16 битов. Фактически, все, что вы передаете или извлекаете из SQL SERVER через PDO, будет иметь размер 8 бит. Как это «доказать»? Вот :
こんにちは
,Сначала вы должны знать, что PHP рассматривает строку как двоичную и что (если она установлена таким образом) будет хранить их в UTF-8.
Так что, если мы посмотрим на двоичное представление こんにちは
, ты получишь E38193E38293E381ABE381A1E381AF
который также является двоичным представлением, которое SQL SERVER даст вам для ã“ã‚“ã«ã¡ã¯
, (зависит от вашего сопоставления)
Далее, давайте поместим его в UTF-16, потому что это формат NVARCHAR.
$ utf16_string = mb_convert_encoding (‘こ ん に ち は’, ‘UTF-16LE’);
Следующее изменит двоичное представление в PHP こんにちは
в 533093306B3061306F30
который является именно двоичным представлением こんにちは
в SQL SERVER NVARCHAR.
S0“0k0a0o0
Бинарное представление SQL SERVER S0“0k0a0o0
в VARCHAR есть 533093306B3061306F30
который также является двоичным представлением こんにちは
в NVARCHAR.
Грязный раствор
Вы можете использовать следующее для сохранения и извлечения данных Unicode в SQL SERVER через PDO ODBC, но это уродливо …
Вы хотите преобразовать данные в точно такое же двоичное представление, как SQL SERVER NVARCHAR
будет хранить его
mb_convert_encoding (‘こ ん に ち は’, ‘UTF-16LE’);
Вы хотите получить его как двоичный файл на стороне SQL SERVER, а затем преобразовать его в NVARCHAR.
@binary VARBINARY (40)
SELECT @string = CONVERT (NVARCHAR (20), @binary);
На данный момент у вас есть こんにちは
в вашей базе данных. Чтобы получить его, вы хотите отправить его в PHP как двоичный файл
Как только вы получите двоичный файл в PHP, PHP уже преобразует его в шестнадцатеричную строку … Итак, вы хотите преобразовать шестнадцатеричную строку в двоичную, а затем изменить кодировку с utf-16 на utf-8.
$ result = mb_convert_encoding (hex2bin ($ string), ‘UTF-8’, ‘UTF-16LE’);
И ты вернешься со своим こんにちは
когда вы откликаетесь на свою веб-страницу.
По сути, это то, что драйвер SQL должен делать для меня вместо того, чтобы я делал это вручную.
Я забыл что-то настроить или я должен сделать это вручную?
Нет, я не думаю, что вы забыли что-то настроить. На самом деле, ваше объяснение — лучшее, что я нашел на данный момент в отношении давних «проблем» между драйверами ODBC для PHP и Microsoft. Эти вопросы особенно озадачивают, учитывая, что Страница PDO_ODBC говорит:
В Windows PDO_ODBC … является рекомендуемым драйвером для подключения к базам данных Microsoft SQL Server.
Тем не менее, на Windows они также предлагают PDO_SQLSRV который на самом деле, кажется, работает правильно.
Похоже, что PDO_ODBC «не имеет никакого понятия о NVARCHAR», а не PDO в целом.
(Подобные проблемы возникают при попытке использовать PHP с Microsoft Access ODBC, если задействованы символы Юникода)
Вывод: поддержка PHP для ODBC по-прежнему остается беспорядком, по крайней мере в том, что касается баз данных Microsoft.
Других решений пока нет …