(2013/5/19 変更:rawurlencode()はRFC3986なのにRFC1738と書いてたので訂正。)
まずはurlencode()とrawurlencode()を比較。
- urlencode()
- 半角チルダ(~)を%7Eに変換する
- 半角スペースをプラス(+)に変換する
- rawurlencode()
- 半角チルダ(~)の変換についてはPHPのバージョンによって違う
- PHP 5.2.xまでは、%7Eに変換する
- PHP 5.3.0からは、%7Eに変換しない(チルダのまま)
- 半角スペースを%20に変換する
rawurlencode()は
RFC1738 RFC3986に沿った変換とされているので、基本的にはurlencode()よりrawurlencode()の方が無難。
ただし、RFC
1738 3986ではチルダを%7Eに変換しない。
ちなみに、RFC1738はその後、
RFC3986によって更新されているが、RFC3986はパッと見た感じではURLエンコードについては(JavaScriptのencodeURIComponent()で使われるRFC2396の方ではなく、)RFC1738を踏襲しているようだ。(2013/5/19 追記:一部変更されてる。)
Amazonの新しいAPIでも、RFC3986によるURLエンコードを使っている。(参考:
Amazon Product Advertising API への対応(PHP版) - もやし日記)
次に、
http_build_query()の話。
http_build_query()は便利だが、URLエンコードの内容はurlencode()と同じなのが残念。
RFC
1738/3986に沿った形にするには、もう1つ変換を咬ませなければならない。
//例
function encodeAlongRFC1738($str) {
return strtr($str, array('%7E' => '~', '+' => '%20'));
}
echo encodeAlongRFC1738(http_build_query($arr));
上記の変換は、PHP5.2までのrawurlencode()にも使える。
あとは実験結果。上記のencodeAlongRFC
1738()も交えて。
元の文字
"~_ _+"
urlencode()の場合
変換結果
"%7E_+_%2B"
urldecode()すると
"~_ _+"
rawurldecode()すると(正しくデコードできない)
"~_+_+"
rawurlencode()の場合(PHP 5.2)
変換結果
"%7E_%20_%2B"
urldecode()すると
"~_ _+"
rawurldecode()すると
"~_ _+"
rawurlencode()の場合(PHP 5.3)
変換結果
"~_%20_%2B"
urldecode()すると
"~_ _+"
rawurldecode()すると
"~_ _+"
urlencode() + encodeAlongRFC1738()の場合
変換結果
"~_%20_%2B"
urldecode()すると
"~_ _+"
rawurldecode()すると
"~_ _+"
元の配列
array("test[0]" => "~_ _+")
http_build_query()の場合
変換結果
"test%5B0%5D=%7E_+_%2B"
urldecode()すると
"test[0]=~_ _+"
rawurldecode()すると(正しくデコードできない)
"test[0]=~_+_+"
http_build_query() + encodeAlongRFC1738()の場合
変換結果
"test%5B0%5D=~_%20_%2B"
urldecode()すると
"test[0]=~_ _+"
rawurldecode()すると
"test[0]=~_ _+"
urldecode()はurlencode()に対してもrawurlencode()に対しても使える。
参考:
URIに使ってよい文字の話 - RFC2396 と RFC3986 - Text::Easyhacking