В качестве обходного пути вы можете просто заставить код, получающий POST, отвечать на данные приложения / json. Для PHP я добавил код ниже, разрешив мне POST для него либо в форме, либо в JSON.
//handles JSON posted arguments and stuffs them into $_POST
//angular's $http makes JSON posts (not normal "form encoded")
$content_type_args = explode(';', $_SERVER['CONTENT_TYPE']); //parse content_type string
if ($content_type_args[0] == 'application/json')
$_POST = json_decode(file_get_contents('php://input'),true);
//now continue to reference $_POST vars as usual
В конечном счете эта проблема не может быть решена простым способом, не используя повторно кодированные строки (UTF-8 в †’ Windows 1252 или ISO-8859-1), как предложено О¤О–О©О¤О–О™ОџОҐ из-за очевидной ошибки PHP, как обнаружено Huppie. Для суммирования проблемы я создал следующий фрагмент кода, который ясно демонстрирует, что проблемой является strcoll () функция при использовании 65 001 Windows-UTF-8-codepage.
function traceStrColl($a, $b) {
$outValue=strcoll($a, $b);
echo "$a $b $outValue\r\n";
return $outValue;
}
$locale=(defined('PHP_OS') && stristr(PHP_OS, 'win')) ? 'German_Germany.65001' : 'de_DE.utf8';
$string="ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜabcdefghijklmnopqrstuvwxyzäöüß";
$array=array();
for ($i=0; $i<mb_strlen($string, 'UTF-8'); $i++) {
$array[]=mb_substr($string, $i, 1, 'UTF-8');
}
$oldLocale=setlocale(LC_COLLATE, "0");
var_dump(setlocale(LC_COLLATE, $locale));
usort($array, 'traceStrColl');
setlocale(LC_COLLATE, $oldLocale);
var_dump($array);
результат:
string(20) "German_Germany.65001"
a B 2147483647
[...]
array(59) {
[0]=>
string(1) "c"
[1]=>
string(1) "B"
[2]=>
string(1) "s"
[3]=>
string(1) "C"
[4]=>
string(1) "k"
[5]=>
string(1) "D"
[6]=>
string(2) "ä"
[7]=>
string(1) "E"
[8]=>
string(1) "g"
[...]
тот же отрывок работает над машиной Linux без любых проблем, производящих следующий вывод:
string(10) "de_DE.utf8"
a B -1
[...]
array(59) {
[0]=>
string(1) "a"
[1]=>
string(1) "A"
[2]=>
string(2) "ä"
[3]=>
string(2) "Ä"
[4]=>
string(1) "b"
[5]=>
string(1) "B"
[6]=>
string(1) "c"
[7]=>
string(1) "C"
[...]
отрывок также работает, когда использование Windows 1252 (ISO-8859-1) закодировало строки (конечно, mb_* кодировка и локаль должны быть изменены тогда).
я зарегистрировал отчет об ошибках на bugs.php.net : Ошибка № 46165 strcoll () не работает со строками UTF-8 в Windows . При испытании той же проблемы можно дать обратную связь команде PHP на странице отчета об ошибках (два другой, вероятно, связанный, ошибки были классифицированы как поддельный - я не думаю, что эта ошибка поддельная ;-).
Благодаря всем Вам.
Обновление по этой проблеме:
Даже при том, что дискуссия по поводу этой проблемы показала, что мы, возможно, обнаружили ошибку PHP с strcoll()
и/или setlocale()
, это - ясно не случай. Проблемой является скорее ограничение реализации Windows CRT setlocale()
(PHPs setlocale()
является просто тонкой оберткой вокруг вызова CRT). Следующее является цитатой страница MSDN "setlocale, _wsetlocale" :
набор доступных языков, кодов страны/региона и кодовых страниц включает все поддерживаемые Win32 NLS API кроме кодовых страниц, которые требуют больше чем двух байтов за символ, таких как UTF-7 и UTF-8. Если Вы предоставляете кодовую страницу как UTF-7, или UTF-8, setlocale перестанет работать, возвращая ПУСТОЙ УКАЗАТЕЛЬ. набор языка и кодов страны/региона, поддерживаемых setlocale, перечислен в Строках Языка и Страны/Региона.
поэтому невозможно использовать осведомленные о локали строковые операции в PHP в Windows, когда строки многобайтовые закодированный.
Используя Ваш пример с кодовой страницей 1252, работавшей превосходный здесь на моей машине разработки окон.
$array=array('Birnen', 'Äpfel', 'Ungetüme', 'Apfel', 'Ungetiere', 'Österreich');
$oldLocal=setlocale(LC_COLLATE, "0");
var_dump(setlocale(LC_COLLATE, 'German_Germany.1252'));
usort($array, 'strcoll');
var_dump(setlocale(LC_COLLATE, $oldLocal));
var_dump($array);
... надрез...
Это было с PHP 5.2.6. btw.
<час> вышеупомянутый пример неправильный , это использует кодирование ASCII вместо UTF-8. Я действительно прослеживал strcoll () вызовы и смотрел, что я нашел:function traceStrColl($a, $b) {
$outValue = strcoll($a, $b);
echo "$a $b $outValue\r\n";
return $outValue;
}
$array=array('Birnen', 'Äpfel', 'Ungetüme', 'Apfel', 'Ungetiere', 'Österreich');
setlocale(LC_COLLATE, 'German_Germany.65001');
usort($array, 'traceStrColl');
print_r($array);
дает:
Ungetüme Äpfel 2147483647 Ungetüme Birnen 2147483647 Ungetüme Apfel 2147483647 Ungetüme Ungetiere 2147483647 Österreich Ungetüme 2147483647 Äpfel Ungetiere 2147483647 Äpfel Birnen 2147483647 Apfel Äpfel 2147483647 Ungetiere Birnen 2147483647
я действительно находил [приблизительно 113] отчеты об ошибках , которые были отмечены, будучи поддельными ... Лучший выбор, который Вы имеете, регистрирует отчет об ошибках, который я предполагаю хотя...
Ваше сопоставление должно соответствовать набору символов. Так как Ваши данные являются закодированным UTF-8, необходимо использовать сопоставление UTF-8. Это можно было назвать по-другому на различных платформах, но хорошее предположение будет de_DE.utf8
.
В системах UNIX, можно получить список в настоящее время устанавливаемых локалей с командой
locale -a
Это - очень сложное выпуск , так как закодированные данные UTF-8 могут содержать любой символ Unicode (т.е. символы от многой 8-разрядной кодировки, которая сопоставляет по-другому в различных локалях).
, Возможно, если Вы преобразовали свои данные UTF-8 в Unicode (не знакомый с PHP unicode функции, извините) и затем нормализовали их в , NFD или NFKD и затем сортирующий на кодовых точках могли бы дать некоторое сопоставление, которое будет иметь смысл Вам (т.е. прежде "Г „").
Проверка ссылки я обеспечил.
РЕДАКТИРОВАНИЕ: так как Вы упоминаете, что Ваши входные данные ясны (я принимаю их всю осень в "кодовой странице" 1252 окон), тогда необходимо сделать следующее преобразование: UTF-8 в †’ Unicode в †’ Windows 1252, по которому Windows 1252 закодировал данные, делает вид, выбирающий локаль "CP1252".