簡単なフォーム
例
ソース
<?php
if (isset($_POST['onamae']) && $_POST['onamae'] != '') {
$x = htmlspecialchars($_POST['onamae']);
echo "<p>こんにちは,$x さん。</p>";
}
?>
<form action="form.php" method="post">
<p>お名前: <input name="onamae" size="20"></p>
</form>
< > & "
といったHTMLで特別な意味を持つ文字を
< > & "
に変換する関数 htmlspecialchars()
を使っています。この理由はセキュリティ上の配慮をご覧ください。
PHP 5.4より古いPHPでは,htmlspecialchars() に文字コードも指定するほうが安全性が増します。UTF-8を使っているなら
$x = htmlspecialchars($_POST['onamae'], ENT_COMPAT, 'UTF-8');
のようにします。2番目の引数 ENT_COMPAT はデフォルトの挙動を指定するものですが,文字コードを第3引数に指定するために入れておきます。以下では簡単にするために文字コード指定をほとんど省略しています。
action="form.php" の部分は,自分のファイル名を書きます。もしデフォルトのファイル名(index.html や index.php)の場合は action="./" と書きます。
なお,現在のHTML標準では,このように action= が自分自身の場合は,action="..." という指定を省略して,<form method="post"> だけにすることができます。
labelを使おう
上の例は実際には次のように書かれています。
<form action="form.php" method="post"> <p><label>お名前: <input name="onamae" size="20"></label></p> </form>
このように label を使うと,ラベル(上の例では「お名前」)をクリックすれば,入力欄に入力可能な状態になります。label のこの動作は,厳密にはHTML5では必須とされていませんが,多くのブラウザでサポートされているようです。
上の形の label はIE6では対応していませんでしたので,以前のこのページでは次の書き方を推奨していました。
<form action="form.php" method="post"> <p><label for="onamae">お名前:</label> <input id="onamae" name="onamae" size="20"></p> </form>
もうIE6はないので大丈夫でしょう。
最初のテキストボックスを選択した状態にするには
ページを開くと最初のテキストボックスがフォーカスされるようにするには,HTML5で新しく導入された autofocus というオプションを使うのが簡単です:
<p><label>お名前: <input name="onamae" size="20" autofocus></label></p>
HTML5以前のブラウザで使えるようにするには,
<p><label>お名前: <input id="onamae" name="onamae" size="20"></label></p>
のように id を付けておき,bodyタグに
<body onload="document.getElementById('onamae').focus()">
のような細工をします(JavaScript講座)。
ポストされたかの判断のいろいろ
上の例では,名前が入力されているかどうかを if (isset($_POST['onamae']) && $_POST['onamae'] != '')
で判断しています。これ以外に次のような判断法が考えられますが,意味は少しずつ違います。
if (isset($_POST['onamae']))- このページを最初に訪れたときは
$_POST['onamae']がセットされていません(var_dump($_POST['onamae'])を表示するとNULLとなります)ので,これで判断できます。ただ,このページで何も入力しないで Enter キーを押した場合は空文字列""がセットされていますので,「こんにちは, さん」と表示されてしまいます。 if (!empty($_POST['onamae']))- 空文字列には反応しなくなりますが,
0と入力しても無入力と判断されてしまいます。 if ($_POST['onamae'])- 同上。
if ($_POST['onamae'] != '')- 空文字列でないことを判断します。
$_POST['onamae']がセットされていない場合には,警告が出ることがありますが,正しく処理されます。 if ($_POST['onamae'] !== '')- 空文字列でないことを(より厳密に)判断します。
$_POST['onamae']がセットされていない場合には,警告が出ることがあるだけでなく,「こんにちは」が表示されてしまいます。 if (isset($_POST['onamae']) && $_POST['onamae'] != '')$_POST['onamae']が定義され,かつ空文字列でないことを判断します。if (@$_POST['onamae'] != '')- このように
@をかぶせることによってエラーや警告が出るのを抑制します。事実上,isset($_POST['onamae'])のチェックをしたかのような振舞いになります。
isset(...) は,セットされているか(is set?)を調べる命令です。複数のものがすべてセットされているかを調べるには,isset($_POST['onamae'], $_POST['email']) のように連続して書くことができます。
上でも書きましたが,存在しない $_POST['onamae']
を使うと,
"PHP Notice: Undefined index: onamae in /home/okumura/public_html/php/form.php on line 17”
のような警告が出ることがあります。
警告が(画面またはApacheのerror_logに)出ないようにするには,PHPの設定ファイルphp.iniの
error_reporting = E_ALL
を
error_reporting = E_ALL & ~E_NOTICE
または
error_reporting = E_ALL & ~E_NOTICE | E_STRICT
のようにします。
PHP 5.2.0 以降では,より安全な入力として filter_input() 関数があります:
$x = htmlspecialchars(filter_input(INPUT_POST, 'onamae'));
if ($x != "") {
echo "<p>こんにちは,$x さん。</p>";
}
CSRF対策
$_SERVER['HTTP_REFERER'] を調べれば,不正な書き込みが検出できます。
ただし,HTTP_REFERERを送らないブラウザがあると,ややこしくなります。
セッション管理を使う対策のほうが一般的です。高木さんのクロスサイトリクエストフォージェリ(CSRF)の正しい対策方法をご覧ください。
具体的には,一つ前のページのformの中に
<input type="hidden" name="sessionid" value="<?php echo htmlspecialchars(session_id(), ENT_COMPAT, 'UTF-8'); ?>">
と書いておき,最終処理をするページで
if ($_POST['sessionid'] != session_id()) die("だめよ");
のようなチェックをします。