БлогNot. PHP: urlencode и urldecode - что нужно для скриптов в однобайтовой кодировке

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 [10849 просмотров]


теги: памятка php

показать комментарии (1)