Иногда бывает так, что мы получаем массив, в котором элементы имеют кодировку, которая нам без надобности. Необходимо преобразовать все элементы массива в нужную нам кодировку. Когда массив одномерный - это не составляет труда. Но когда мы имеем многомерный массив, могут возникнуть трудности - нам ведь надо опускаться на неопределенную глубину. Следующая маленькая функция решит эту тривиальную задачу:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
function iconvArray($inputArray,$newEncoding){
$outputArray=array();
if ($newEncoding!=''){
if (!empty($inputArray)){
foreach ($inputArray as $element){
if (!is_array($element)){
$element=iconv(mb_detect_encoding($element),
$newEncoding,$element);
} else {
$element=iconvArray($element);
}
$outputArray[]=$element;
}
}
}
return $outputArray;
}
Просто и… рекурсивно ;)
Согласен, моя функция была написана для простых, но не ассоциативных массивов. Мне уже довелось ее переписать, когда я при разработке получал ассоциативный массив. Твою функцию, кстати, можно дополнить изменением кодировки в ключе, т.к. в ассоциативных массивах можно задавать ключи, состоящие из национальных символов (н-р, кириллицы), и, конечно же, рано или поздно, придется столкнуться с такими массивами.
Смутно представляю себе человека, который станет ключи в массивах писать буквами отличными от общепринятой латиницы, и цифрами непохожими на арабские. Разве что какой-то нечеловек, выносящий мозг своими потугами в MSAccess.
http://fucking-great-advice.ru/advice/1928/
Кстати также замечу, что в случае перекодирования из cp1251 mb_detect_encoding абсолютно бесполезна, потому что всегда вернёт UTF-8, что сводит всю эту функцию к состоянию полной ненужности. А учитывая, что русскоязычных граждан с русскоязычными сайтами интересует прежде всего перекодировка из cp1251 в UTF-8 (например, чтобы получить JSON для AJAX-запросов), то это всё действительно не нужно. Проще знать входящую и исходящую кодировки и тупо так и писать: iconvArray(“cp1251”, “UTF-8”, $_POST);
mb_detect_encoding над cp1251 вернет в качестве результата ASCII, так что здесь тоже можно сориентироваться - добавить условие. В любом случае, mb_ функции для однобайтовых кодировок не предназначены.
В том-то и потеха, что префикс “mb” означает “мультибайт”, и всякие однобайтные кодировки просто игнорирует.
Специально попробовал: ASCII возвращает если нет букв. С буквами возвращает непременно UTF-8.
Верно. Если требуется преобразовывать cp1251 моей функцией, то наиболее простым решением будет, конечно, предложенное тобой.
Хорошая функция, свое дело делает. А вот если в исходном массиве в начале стоит буква Ё, ему сносит крышу, как полечить, уважаемые?
Вот пример такого массива: ( [0] => Ёмкость для воды )
Да нет, разумеется насчет “utf-8” не универсально =) я скинул пример именно своей функции, а у меня там всё чисто на utf-8, мне текущее определение ни к чему. Мой пример был лишь для наглядности работы с указателями на массивы, дабы не забивать лишнюю память, создавая новые массивы. Особенно, если работаешь с большими дампами.
Там есть еще пару чисто технических ошибочек, в “iconv” и рекурсивном вызове функции. А вообще ты прав что ключики нужно тоже декодировать.
Peace.
Стесняюсь спросить, а что означает сие $this->iconvArray($element, $newEncoding); в девятой строке? Откуда взялся некий объект $this? Или я чего-то не вижу, что видят все остальные?
Не надо стесняться ;). Это я забыл подправить функцию, когда копировал её из своего класса :) . Спасибо за наводку, я поправил код.
Полечил, явно указал кодировку $element=iconv($newEncoding,”UTF-8”,$element);
Как раз писал комментарий в ответ на твой вопрос :) . Можно попробовать ещё вот это http://phpclub.ru/faq/CharsetDetection для определения кодировки. Правда я не пользовался этими скриптами, не могу сказать насколько они корректно определяют кириллицу.
А как насчет использования указателей? Заместо генерации нового массива. Вот пример моей функции function Decode(&$sVal) { if(is_array($sVal)) { foreach($sVal as &$bVal) { CAllSplitTest::Decode(&$bVal); } } else { $sVal = iconv(“utf-8”,LANG_CHARSET,$sVal); } }
Один момент - utf-8 здесь не универсально. Причина этому - если данные приходят извне, то они могут быть в совершенно произвольной кодировке. Также, стоит учитывать и то, что кодировка базы данных, из которой приходят данные, тоже может смениться. Я бы сделал здесь сам себе ещё одно замечание :) - mb_detect_encoding(), которую я использую в статье, возвращает значение ASCII, если в качестве параметра ей отправлена строка в какой-нибудь однобайтовой кодировке, типа Windows-1251. Такое поведение mb_detect_encoding() стоит обрабатывать дополнительно.
Позволю себе немного отредактировать (справить) твою функцию:
function iconvArray($inputArray,$newEncoding){ $outputArray=array(); if ($newEncoding!=’’){ if (!empty($inputArray)){ foreach ($inputArray as $key => $element){ if (!is_array($element)){ $element=iconv($newEncoding,mb_detect_encoding($element),$element); } else { $element=$this->iconvArray($element, $newEncoding); } $outputArray[$key]=$element; } } } return $outputArray; }
В строке $element=iconv ($newEncoding,mb_detect_encoding ($element),$element); надо поменять местами старую и новую кодировку $element=iconv (mb_detect_encoding ($element),$newEncoding,$element);