簡単なフォーム
例
ソース
<?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("だめよ");
のようなチェックをします。