PHP: urlencode и urldecode - что нужно для скриптов в однобайтовой кодировке
Распространённая у новичков проблема - функции urlencode и urldecode работают "неожиданно", если кодировка - не UTF-8.
Да, с одной стороны urldecode
должна думать, что её аргумент в UTF-8:
data should first be encoded as octets according to the UTF-8 character encoding
отсюда
Поэтому, делая всё в однобайтовой кодировке, например, Windows-1251, мы рискуем увидеть на выходе юникодовские "кракозябры":
<!DOCTYPE html PUBLIC "–//W3C//DTD HTML 4.01//EN"> <html><head> <meta http–equiv="Content–Type" content="text/html; charset=Windows–1251" /> <title>Пример</title> </head> <body> <?php $q = $_GET['q']; echo urldecode ($q); //привет ?> </body></html>
Здесь строка получена параметром URL и скрипт под именем script.php
вызван из корневой папки локалхоста
запросом
http://localhost/script.php?q=привет
В данном случае браузер получает строку "как есть", в нём при этом выставлена кодировка Windows-1251 и в Denwer тоже.
Если передать скрипту уже URL-кодированный однобайтовым кодом "привет" запросом
http://localhost/script.php?q=%EF%F0%E8%E2%E5%F2
то всё, конечно, напечатается нормально. А вот для "двухбайтового" URL-запроса
http://localhost/script.php?q=%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82
скрипт опять покажет "кракозябры" на странице и правильный "привет" в адресной строке - кодировка-то у нас всюду однобайтовая :) В общем, если входная кодировка другая, чем Юникод, решением проблемы будет iconv.
Так, показать URL-кодированную запись переданного через URL "привета" и сам исходный "привет" можно в виде
$q = $_GET['q']; echo urlencode ($q); //%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82 echo '<br>'.iconv("UTF-8", "Windows-1251", $q); //привет
(показано только содержимое тега <?php ?>
). Как видим, переменные адресной строки браузера предполагаются заданными в Юникоде, даже если на локалхосте и в коде страницы указана другая кодировка.
Если сам файл со скриптом тоже в кодировке Windows-1251 и переменная $q
задана непосредственно в скрипте (или прочитана из файла, базы данных в той же кодировке), её декодировать не нужно:
$q = 'привет'; echo $q; //привет echo '<br>'.urlencode ($q); //%EF%F0%E8%E2%E5%F2
Обратите внимание, что из-за однобайтовой кодировки в данном случае получатся не юникодовские "октеты", а нормальные байты. Преобразование будет обратимо и в однобайтовой кодировке:
echo '<br>'.urldecode(urlencode ($q)); //привет
21.09.2015, 17:13 [11041 просмотр]