【PHP/JavaScript】URLエンコードを徹底比較
[ PR ]
久しぶりの更新です。もうお気づきかもしれませんが当ページを自鯖に移行したため時間がかかりました。
さて今回は、URLエンコードについて検証してみます。
URLエンコードとデコードの相性
URLエンコードと一重に言っても、PHPでも以下のような種類があります。
- urlencode
- rawurlencode
- base64_encode
実際には、「JavaScriptでエンコードしてPHPでデコードする」といったケースも少なくないですよね。この場合はさらに以下の総当りを考えなければなくなります。
# | encodeURI | encodeURI- Component |
bae64.encode (※) |
---|---|---|---|
urldecode | ? | ? | ? |
rawurldecode | ? | ? | ? |
base64_decode | ? | ? | ? |
(※) サードパーティのライブラリを使う場合
もうここまでくると、どの組み合わせを使えばいいのかさっぱりわかりません。(汗)
URLエンコードの都市伝説
先程の総当りですが、以下のようにするとうまくいくという都市伝説があります。
- encodeURI と urldecode
- encodeURIComponent と rawurldecode
- base64_encode と Base64.decode(サードパーティ)
確かに意味合い的にはうまくいきそうですが、本当に上手くいくかはわかりません。
ということで、実際はどうなのか調べてみることにしました。
検証方法
できるだけ多くのケースを自動的に判断できるように、以下の方法を取りました。
- (1) PHPでエンコードしたものをJavaScriptでデコードする
- (2) PHPとJavaScriptでそれぞれ同じものをエンコードして、結果を比較する
- (3) PHPとJavaScriptでそれぞれ同じものを1万回エンコードして、速度を比較する
この3つの方法に使ったソースコードを以下に貼っておきます。
- (1) encode_decode.php
- (2) encode_tests.php
- (3) encode_time.php
実行結果
実際のPHPをここで走らせてみたかったのですが、サーバ負荷が大きいので結果として出力されるHTMLだけを貼っておきます。
(1) PHPでエンコードしたものをJavaScriptでデコードする
考察
この結果を見ると、urlencode と decodeURI は上手くいかない ということがわかります。
意外にも urlencodeの結果をdecodeURIComponentできちんとデコードできているようです。
- urlencode → decodeURI NG
- rawurlencode → decodeURIComponent OK
- Base64.encode → base64_decode OK
ただ必ずしも逆はこうなるとは限らないので、気になる方は手動で検証してください。
(2) PHPとJavaScriptでそれぞれ同じものをエンコードして、結果を比較する
考察
最後の方の結果を見ると、JavaScriptのencodeURIは「/:&+=:;/?,#$」をエスケープしていないということがわかります。
また、encodeURIComponentの方も「~!*()_-」をエスケープしていないようですね。
ブラウザによって異なる可能性はありますが、
- encodeURI
- encodeURIComponent
をGETとPOSTに使うのは、若干不安がありますね。
ただ、encodeURIComponent はある程度エスケープを強化しているので、ある特定の文字列以外では上手くいくと思います。(そうじゃないと困ります 笑)
(3) PHPとJavaScriptでそれぞれ同じものを1万回エンコードして、速度を比較する
考察
この結果を見るとencodeURIが重いですが、何回も行うと結果がバラバラで、18ms〜60ms と変動しました。
PHPの方はサーバ性能に比例するようで、Hetemlで一度実行したときは、すべて 7ms〜9ms でした。
結論
一番良好な結果だったエンコード方式はBase64
以上の結果を見ると、全ての場合に有効なのが Base64 でした。
ただしJavaScript側で標準でサポートされていないため、ライブラリを使わないといけない欠点があります。
encodeURIComponent & rawurldecode でほとんどの場合がOK
ライブラリ不要で動くものとしては、概ね encodeURIComponent と rawurldecode が有効だということがわかりました。
ただしこの場合も、特定の記号には気をつけたほうが良さそうです。
encodeURI は目的によっては使わないほうがいい
一番結果がよくなかったのが、encodeURIですね。POSTやGETに使うとエラーが起こる可能性があるので気をつけてください。
まとめ
意外と安易に使いがちなエンコードですが、今回紹介した他にも
- escape
- mysqli_real_escape_string
- mysqli_escape_string
など種類が多いですよね。
用途に応じてそれぞれ異なったエンコードが行われるので、なんとなく使うのではなくて、気をつけて使いたいですね。
リックテレコム
売り上げランキング: 1,175