こんにちは、かつコーチです。
前回はDateTimeクラスで日付・時刻を扱う方法を解説しました。
今回は、PHPでWebアプリケーションを作るうえで避けて通れない「フォームから送られてきた値を受け取る」方法を解説します。
お問い合わせフォーム、検索ボックス、ログインフォームなど、ユーザーが何かを入力して送信する機能のほとんどが、今回解説する $_GET と $_POST の仕組みの上に成り立っています。
私が初めてこの2つを学んだときに一番混乱したのが、「どっちを使えばいいのか分からない」という点でした。
今回はその判断基準も含めて、しっかり整理していきます。
_GETと_POSTとは
スーパーグローバル変数という特別な存在
$_GET と $_POST は、スーパーグローバル変数と呼ばれる特別な変数です。
自分で定義しなくても、PHPが自動的に用意してくれていて、どこからでも(関数の中からでも)呼び出せます。
これらの中には、ユーザーがフォームに入力した値や、URLに付与されたパラメータが、連想配列の形で自動的に格納されています。
$_GETの基本
$_GET は、URLの末尾に ?key=value の形で付けられたパラメータを受け取るための変数です。
https://example.com/search.php?keyword=PHP&page=2
このURLでアクセスされたとき、search.php の中では次のように値を取り出せます。
<?php
$keyword = $_GET["keyword"];
$page = $_GET["page"];
echo "検索キーワード: " . $keyword . "\n";
echo "ページ番号: " . $page . "\n";
// 検索キーワード: PHP
// ページ番号: 2
$_GET はURLにパラメータがそのまま表示されるのが特徴です。
検索結果ページのように、URLを見ただけで「何を検索した結果か」が分かるページとの相性がよく、ブックマークや共有もしやすくなります。
$_POSTの基本
$_POST は、HTMLの <form> タグの method="post" で送信された値を受け取るための変数です。
<form method="post" action="register.php">
<input type="text" name="username">
<input type="password" name="password">
<button type="submit">登録</button>
</form>
<?php
// register.php
$username = $_POST["username"];
$password = $_POST["password"];
echo "ユーザー名: " . $username;
$_POST は値がURLに表示されない点が $_GET との大きな違いです。
_GETと_POSTの使い分け
判断基準は「データの性質」
「結局どっちを使えばいいの?」という疑問は、初心者の頃に誰もが一度は感じるところだと思います。
判断基準はシンプルで、送るデータの性質によって決まります。
| 観点 | $_GET | $_POST |
|---|---|---|
| データの見え方 | URLに表示される | URLに表示されない |
| データ量の目安 | 少なめ(URL長に制限あり) | 制限が緩い |
| 用途の例 | 検索、ページ番号、絞り込み条件 | ログイン、会員登録、パスワード変更 |
| ブックマーク | 可能(同じ結果を再現できる) | 基本的に不向き |
「URLに残っても問題ないデータ」は $_GET、「見られたくない・毎回送信すべきデータ」は $_POST、という基準で選ぶと迷いにくいです。
パスワードのような機密情報を $_GET で送ってしまうと、URLの閲覧履歴やサーバーのアクセスログにパスワードがそのまま残ってしまう危険があります。
ログインフォームは必ず $_POST を使うようにしましょう。
つまずきやすいポイント:値が存在しないときのエラー
かつコーチが実際にハマったエラー
私がまだ駆け出しの頃、お問い合わせフォームを作っていて次のようなエラーに遭遇しました。
Warning: Undefined array key "email" in /var/www/html/contact.php on line 5
原因は単純で、フォームを送信せずに直接 contact.php のURLにアクセスしたとき、$_POST["email"] というキー自体が存在していなかったためです。
フォーム経由でアクセスすることしか想定していなかったため、こうした「値が存在しないパターン」への対策を忘れていました。
❌ Before:値の存在チェックをせずにいきなり使う
<?php
// contact.php
$name = $_POST["name"];
$email = $_POST["email"];
$message = $_POST["message"];
echo "お問い合わせありがとうございます、" . $name . "様";
フォームを経由せずアクセスされた場合や、フォーム側で name 属性を書き間違えていた場合、$_POST["name"] のキーが存在せず、警告(Warning)が発生します。
警告が出ても処理自体は止まりませんが、意図しない空文字が処理に紛れ込み、後続の処理でさらに別のエラーを引き起こす原因になります。
✅ After:isset() や null合体演算子で存在チェックをする
<?php
// contact.php
$name = $_POST["name"] ?? "";
$email = $_POST["email"] ?? "";
$message = $_POST["message"] ?? "";
if ($name === "" || $email === "" || $message === "") {
echo "未入力の項目があります";
exit;
}
echo "お問い合わせありがとうございます、" . $name . "様";
??(null合体演算子)を使うと、「左側の値が存在しない、またはnullの場合に右側の値を使う」という処理を1行で書けます。
$_POST["name"] ?? "" と書けば、キーが存在しなくても空文字が代入されるだけで、警告は発生しません。
さらに、その後の if 文で「必須項目が空でないか」をチェックすることで、不完全な送信をきちんとはじく処理になっています。
isset() を使って同じことを書くと、次のようになります。
<?php
if (isset($_POST["name"])) {
$name = $_POST["name"];
} else {
$name = "";
}
どちらでも同じ意味になりますが、?? の方が短く書けるので、実務では ?? を使うケースが多い印象です。
セキュリティの基本:入力値をそのまま信用しない
htmlspecialcharsでXSS対策をする
フォームから受け取った値は、外部から送られてきた、信用できないデータとして扱う必要があります。
もし受け取った値をそのまま画面に表示してしまうと、悪意のあるユーザーがHTMLタグやJavaScriptコードを入力欄に埋め込み、意図しないスクリプトを実行させる「XSS(クロスサイトスクリプティング)」という攻撃につながる恐れがあります。
❌ Before:受け取った値をそのまま表示する
<?php
$name = $_POST["name"] ?? "";
echo "こんにちは、" . $name . "さん";
// $nameに <script>alert('攻撃');</script> のような文字列が入っていると
// そのままスクリプトとして実行されてしまう可能性がある
✅ After:htmlspecialcharsで無害化してから表示する
<?php
$name = $_POST["name"] ?? "";
$safeName = htmlspecialchars($name, ENT_QUOTES, "UTF-8");
echo "こんにちは、" . $safeName . "さん";
// <script>タグなどが文字列としてそのまま表示され、実行されなくなる
htmlspecialchars() は、< や > などのHTMLタグとして解釈される記号を、< や > といった「見た目だけ同じ、実行されない文字」に変換してくれる関数です。
フォームから受け取った値を画面に表示するときは、必ず htmlspecialchars() を通す、これはPHPでフォームを扱うときの鉄則として覚えておいてください。
まとめ
この記事のポイント
$_GETはURLパラメータ、$_POSTはフォーム送信の値を受け取るスーパーグローバル変数- 検索条件など「URLに残ってよいデータ」は $_GET、パスワードなど「見られたくないデータ」は $_POST を使う
- 値が存在しない場合に備えて
??(null合体演算子)やisset()でチェックする - フォームの入力値は必ず
htmlspecialchars()で無害化してから画面に表示し、XSS対策をする
次に読むべき記事
フォームの値を受け取れるようになったら、次は「ログイン状態を保持する」ためのセッションの仕組みを見ていきましょう。
→ 次の記事:PHPのセッション(session_start)でログイン状態を保持する方法