PHP: сравнение букв иврита - PullRequest
0 голосов
/ 09 ноября 2018

Я пытаюсь разбить слово на иврите на буквы и получить индекс соответствующего символа.Я установил заголовок UTF-8 и проверил, что кодировка файлов на самом деле UTF-8.Но по какой-то причине PHP не может сделать правильное сравнение символов и не возвращает требуемый идентификатор символа, в то время как если я выведу массив $ text, он выведет его нормально.У меня есть массив букв иврита:

$id_symbols = array(
    280=>'א‬',
    281=>'בּ‬',
    282=>'ב‬',
    283=>'ג‬',
    284=>'ד‬',
    285=>'ה‬',
    286=>'ו‬',
    287=>'ז‬',
    288=>'ח‬',
    289=>'ט‬',
    290=>'י‬',
    291=>'כּ‬',
    292=>'כ‬',
    293=>'ךּ‬',
    294=>'ך‬',
    295=>'ל‬',
    296=>'מ‬',
    297=>'ם‬',
    298=>'נ‬',
    299=>'ן‬',
    300=>'ס‬',
    301=>'ע‬',
    302=>'פּ‬',
    303=>'פ‬',
    304=>'ף‬',
    305=>'צ‬',
    306=>'ץ‬',
    307=>'ק‬',
    308=>'ר‬',
    309=>'שׁ‬',
    310=>'שׂ‬',
    311=>'תּ‬',
    312=>'ת‬',
);

Я отправляю запрос на публикацию на страницу, подобную этой:

header('Content-type: text/html; charset=utf-8');

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL,"http://pr.animizer.net/word-api.php");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,
            "api_key=some_key&text=מילה&font=arial&font_size=30&fore_color=000000&back_color=FFFFFF&template=1,2,3&speed=4");

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$server_output = curl_exec($ch);

curl_close ($ch);

exit($server_output);

Получен запрос POST. Я пытаюсь получить ключ откаждая соответствующая буква иврита:

function mb_str_split($string) {
$strlen = mb_strlen($string);
while ($strlen) {
    $array[] = mb_substr($string,0,1,"UTF-8");
    $string = mb_substr($string,1,$strlen,"UTF-8");
    $strlen = mb_strlen($string);
}
return $array;
}

$text = mb_str_split($_POST['text']); //splitting text into symbols

foreach($text as $t){

    foreach($id_symbols as $key=>$value){
        if($value == $t){
            $word[] = $key;
        }
    }

}



print_r($word);

и вывод

Array
(
)

PS Пытался одинаково выводить русские буквы в одних и тех же файлах, и они работают нормально.Не похоже, что проблема в кодировке

Ответы [ 2 ]

0 голосов
/ 09 ноября 2018

Как @Rei указал в своем ответе, существует проблема с вашим текущим массивом символов. После обрезки символов я заметил, что семь (7) значений, которые имели более одного символа, имели стандартный символ и одно из трех символов точка :

  1. ДИРЕКТОР ИВРИТИЧЕСКОЙ ТОЧКИ ИЛИ MAPIQ (ּ)
  2. ТОЧКА ЗОЛОТОЙ ТОЧКИ (ׁ)
  3. ПУНКТ ИВРИТИЧЕСКОЙ ТОЧКИ (ׂ)

Я написал некоторый код, который преобразует ивритские символы в их десятичные числовые значения кодировки HTML. Если встречается одно из значений point , оно объединяется со следующим символом в массиве, чтобы соответствовать одному из ваших символов. Следующий код работает хорошо для меня:

<?php 

function _uniord($c) {
    if (ord($c{0}) >=0 && ord($c{0}) <= 127)
        return ord($c{0});
    if (ord($c{0}) >= 192 && ord($c{0}) <= 223)
        return (ord($c{0})-192)*64 + (ord($c{1})-128);
    if (ord($c{0}) >= 224 && ord($c{0}) <= 239)
        return (ord($c{0})-224)*4096 + (ord($c{1})-128)*64 + (ord($c{2})-128);
    if (ord($c{0}) >= 240 && ord($c{0}) <= 247)
        return (ord($c{0})-240)*262144 + (ord($c{1})-128)*4096 + (ord($c{2})-128)*64 + (ord($c{3})-128);
    if (ord($c{0}) >= 248 && ord($c{0}) <= 251)
        return (ord($c{0})-248)*16777216 + (ord($c{1})-128)*262144 + (ord($c{2})-128)*4096 + (ord($c{3})-128)*64 + (ord($c{4})-128);
    if (ord($c{0}) >= 252 && ord($c{0}) <= 253)
        return (ord($c{0})-252)*1073741824 + (ord($c{1})-128)*16777216 + (ord($c{2})-128)*262144 + (ord($c{3})-128)*4096 + (ord($c{4})-128)*64 + (ord($c{5})-128);
    if (ord($c{0}) >= 254 && ord($c{0}) <= 255)    //  error
        return FALSE;
    return 0;
}

function mb_str_split($string) {
    $strlen = mb_strlen($string);
    while ($strlen) {
        $array[] = mb_substr($string,-1,1,"UTF-8");
        $string = mb_substr($string,0,$strlen-1,"UTF-8");
        $strlen = mb_strlen($string);
    }
    return $array;
}

$hebrewText = $_POST['text'] //"מילה" used in example;

$text = mb_str_split($hebrewText); //splitting text into symbols

$word = [];

$lookupChrs = array(
    '1488'=>280,
    '14681489'=>281,
    '1489'=>282,
    '1490'=>283,
    '1491'=>284,
    '1492'=>285,
    '1493'=>286,
    '1494'=>287,
    '1495'=>288,
    '1496'=>289,
    '1497'=>290,
    '14681499'=>291,
    '1499'=>292,
    '14681498'=>293,
    '1498'=>294,
    '1500'=>295,
    '1502'=>296,
    '1501'=>297,
    '1504'=>298,
    '1503'=>299,
    '1505'=>300,
    '1506'=>301,
    '14681508'=>302,
    '1508'=>303,
    '1507'=>304,
    '1510'=>305,
    '1509'=>306,
    '1511'=>307,
    '1512'=>308,
    '14731513'=>309,
    '14741513'=>310,
    '14681514'=>311,
    '1514'=>312
    );

foreach($text as $t){
    $lookupChr = _uniord(array_shift($text));
    $lookupChr = (string)$lookupChr;
    //handle accents (two charactrers instead of one)
    if($lookupChr == "1468" || $lookupChr == "1473" || $lookupChr == "1474"){
        //accent detected, combine with next character
        //echo "\"" . $lookupChr . "\":\"" . _uniord(array_shift($text)) . "\"";
        $lookupChr .= _uniord(array_shift($text));
    }
    if($lookupChr != "0"){
        $word[] = $lookupChrs[$lookupChr];
    }
}

print_r($word);

//OUTPUT:
//    Array
//    (
//        [0] => 285
//        [1] => 295
//        [2] => 290
//        [3] => 296
//    )
0 голосов
/ 09 ноября 2018

Проблема с вашим кодом - массив символов.

Последняя часть вашего кода пытается сопоставить 1 символ (символ) с элементами в $id_symbols. Проблема в том, что ни один из этих элементов не имеет 1 символ Они состоят из 2 или 3 символов и поэтому никогда не будут совпадать.

Этот код покажет вам.

foreach($id_symbols as $key => $value) {
    echo $key.' '.$value.' '.json_encode($value)."\n";
}

Выход:

280 א‬ "\u05d0\u202c"
281 בּ‬ "\u05d1\u05bc\u202c"
282 ב‬ "\u05d1\u202c"
283 ג‬ "\u05d2\u202c"
284 ד‬ "\u05d3\u202c"
285 ה‬ "\u05d4\u202c"
286 ו‬ "\u05d5\u202c"
287 ז‬ "\u05d6\u202c"
288 ח‬ "\u05d7\u202c"
289 ט‬ "\u05d8\u202c"
290 י‬ "\u05d9\u202c"
291 כּ‬ "\u05db\u05bc\u202c"
292 כ‬ "\u05db\u202c"
293 ךּ‬ "\u05da\u05bc\u202c"
294 ך‬ "\u05da\u202c"
295 ל‬ "\u05dc\u202c"
296 מ‬ "\u05de\u202c"
297 ם‬ "\u05dd\u202c"
298 נ‬ "\u05e0\u202c"
299 ן‬ "\u05df\u202c"
300 ס‬ "\u05e1\u202c"
301 ע‬ "\u05e2\u202c"
302 פּ‬ "\u05e4\u05bc\u202c"
303 פ‬ "\u05e4\u202c"
304 ף‬ "\u05e3\u202c"
305 צ‬ "\u05e6\u202c"
306 ץ‬ "\u05e5\u202c"
307 ק‬ "\u05e7\u202c"
308 ר‬ "\u05e8\u202c"
309 שׁ‬ "\u05e9\u05c1\u202c"
310 שׂ‬ "\u05e9\u05c2\u202c"
311 תּ‬ "\u05ea\u05bc\u202c"
312 ת‬ "\u05ea\u202c"

Должен быть только один обратный слеш каждый, но у каждого из них есть 2 или 3.

Первая проблема, все они заканчиваются на \u202c. Решение этой проблемы простое: просто удалите их.

Вторая проблема, даже после удаления всех \u202c, есть еще 7 элементов шириной 2 символа. Это 281, 291, 293, 302, 309, 310, 311. Решение этой проблемы: их необходимо заменить их версиями с одним символом.

Например, элемент индекса 293 равен \u05da\u05bc, и его можно заменить на \ufb3a. Смотри https://codepoints.net/U+FB3A

Полагаю, вы можете разобраться с оставшимися 6 символами.

...