dimayakovlev.ru


Почему iconv не возвращает ничего

Переводя текст из одной кодовой страницы в другую, используя PHP функцию iconv(), можно столкнуться с проблемой — iconv() не возвращает ничего. На самом деле, возвращает, но не ожидаемую строку, а логическое значение false. Почему так происходит и что с этим делать?

Предлагаю рассмотреть описанную проблему на конкретном примере: перекодировка текстовой строки из кодовой страницы UTF-8 в KOI8-R. Это частая задача, с которой сталкиваются разработчики, например, при подготовке текста, полученного из формы обратной связи, для отправки его в виде текста письма по электронной почте.

<?php
$text = '« Potato #345 » — a simple portrait of an organic Irish spud — reportedly sold for €1 million.';
echo iconv('UTF-8', 'KOI8-R', $text);
?>

Начиная с версии PHP 5.4, такой код не выведет ничего. Но если посмотреть дамп, то будет видно, что функция iconv() возвращает значение false. А если включен режим вывода сообщений об ошибках, то вы увидите Notice: iconv(): Detected an illegal character in input string in ....

<?php
var_dump(iconv('UTF-8', 'KOI8-R', $text));
?>

Это происходит в тех случаях, когда конвертируемая строка содержит символы, отсутствующие в целевой кодовой странице. В строке из примера я выделил символы, приводящие к появлению ошибки перекодировки из UTF-8 в кодовую страницу KOI8-R:

« Potato #345 » a simple portrait of an organic Irish spud reportedly sold for 1 million.

До версии PHP 5.4, в случае, если функция iconv() встречала проблемные символы в перекодируемой строке, то она возвращала часть строки до первого найденного символа.

Зная об особенности работы функции iconv(), можно выбрать один из следующих методов решения потенциальной проблемы:

  1. предварительно удалить из перекодируемой строки символы, приводящие к ошибке;
  2. использовать специальные флаги, управляющие работой функции.

Конечно, при желании можно использовать первый метод, но он не универсален, так как придётся учитывать все символы, отсутствующие в целевой кодовой странице. Гораздо удобнее и правильно использовать второй метод.

Функция iconv() поддерживает два флага, добавляемых к указываемой целевой кодовой странице:

  • //TRANSLIT – включает режим транслитерации, выполняющий замену символов, которые не могут быть представлены в целевой кодовой странице, на один или несколько символов, наиболее близких по внешнему виду;
  • //IGNORE – включает режим, удаляющий символы, которые не могут быть представлены в целевой кодовой странице.

Следует учитывать, что работа режима //TRANSLIT зависит от реализации iconv() в системе, поэтому этот режим может работать некорректно или не работать совсем, что приведёт к появлению ошибки. Поэтому надёжнее указывать сразу оба флага:

<?php
echo iconv('UTF-8', 'KOI8-R//TRANSLIT//IGNORE', $text);
?>

Результат выполнения функции iconv() с флагами выглядит так:

« Potato #345 » – a simple portrait of an organic Irish spud – reportedly sold for EUR1 million.

Думаю, что теперь у вас не возникнет вопроса о том, что делать и почему “iconv() не возвращает ничего”.