PHP のサンプルコード。 foo パラメータの値と gettype 関数で取得した型を出力する。

sample.php


<?php

function dump($key, $val) {
  $valType = gettype($val);
  echo("${key}: ${val} (${valType})\n");
}

dump('foo', $_GET['foo']);

簡易的に ビルトインウェブサーバー を起動して挙動を見る。


$ php -S 0.0.0.0:8888

他のターミナルから、いろんなパターンでアクセスしてみる。

普通に foo=hello と指定。


$ curl "http://localhost:8888/sample.php?foo=hello"
foo: hello (string)

foo=111&foo=222 と同じパラメータ名で値を2つ指定。後者のパラメータが有効になっている。


$ curl "http://localhost:8888/sample.php?foo=111&foo=222"
foo: 222 (string)

パラメータ名 foo だけ指定して、値は指定しない。この場合は空文字列が取得される。


$ curl "http://localhost:8888/sample.php?foo="
foo:  (string)

パラメータ名 foo を指定しない。この場合は値が NULL になる (そして $_GET に存在しないキーのため Notice メッセージが出力される)。


$ curl "http://localhost:8888/sample.php?"
<br />
<b>Notice</b>:  Undefined index: foo in <b>/Users/hoge/sample.php</b> on line <b>8</b><br />
foo:  (NULL)

日本語「あ」を UTF-8 でエンコードした値「%E3%81%82」を指定。そのまま「あ」が取得できた。おや・・・?


$ curl "http://localhost:8888/sample.php?foo=%E3%81%82"
foo: あ (string)

あやしいので、もうちょっとサンプルコードを書いて調べてみる。

sample2.php


<?php

if ($_GET['foo'] === '%E3%81%82') {
  # エンコードした値のまま
  echo "encoded\n";
}

if ($_GET['foo'] === 'あ') {
  # デコードされている
  echo "decoded\n";
}

「decode」と表示されたので、エンコードした「%E3%81%82」は、$_GET するとデコードされているようだ。


$ curl "http://localhost:8888/sample2.php?foo=%E3%81%82"
decoded

マニュアルを漁ってみると、ちゃんと書いてあった。

警告
スーパーグローバル $_GET および $_REQUEST の内容はすでにデコード済みのものです。 $_GET や $_REQUEST の要素に対して urldecode() を使用すると、予期せぬ危険な結果となります。

PHP: urldecode - Manual
注意:
GET 変数は urldecode() 関数を介して渡されます。

PHP: $_GET - Manual
与えられた文字列中のあらゆるエンコード文字 %## をデコードします。 プラス記号 ('+') は、スペース文字にデコードします。

PHP: urldecode - Manual

今回の環境: Mac OS X El Capitan + PHP 7.0


$ uname -mrsv
Darwin 15.5.0 Darwin Kernel Version 15.5.0: Tue Apr 19 18:36:36 PDT 2016; root:xnu-3248.50.21~8/RELEASE_X86_64 x86_64

$ php -v
PHP 7.0.7 (cli) (built: May 27 2016 11:13:44) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies

tags: php

Posted by NI-Lab. (@nilab)