まえがき
PHPプログラミングにおいて、$_POSTスーパーグローバル変数は、HTTP POSTリクエストを通じて送信されたデータを扱う際に不可欠です。
この記事では、$_POSTの基本的な使い方とフォームデータの安全な取り扱い方法を紹介します。
$_POST変数の基本
$_POSTは、HTTP POSTリクエストを通じて送信されたデータを含むPHPのスーパーグローバル配列です。
主にHTMLフォームからデータを受け取る際に使用されます。
基本的な使い方
HTMLフォームのデータは、フォームが送信された後のPHPスクリプトで$_POST配列を通じてアクセス可能です。
HTMLフォームの例
<form method="post" action="submit.php">
<input type="text" name="username">
<input type="submit" value="Submit">
</form>
PHPスクリプト
<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$username = $_POST['username'];
echo "Submitted Username: " . $username;
}
この例では、ユーザー名を入力するフォームからデータを受け取り、表示しています。
フォームデータの取得
$_POSTを使用してフォームデータを取得する際、フォームの各入力要素のname属性が$_POST配列のキーに対応します。
セキュリティとバリデーション
- データのバリデーション:$_POSTから取得したデータは、常にバリデーション(有効性確認)を行うべきです。これには、データの形式のチェックや、期待されるデータタイプへの変換が含まれます。
- エスケープ処理:$_POSTデータをHTMLとして出力する前には、クロスサイトスクリプティング(XSS)攻撃を防ぐためにエスケープ処理を行う必要があります。
実際に動かしてみる
ここからはdocker composeを使用してフォームデータと$POST変数の実際の動作を確認してみましょう。
1. プロジェクトのディレクトリを作成
ターミナルで以下のコマンドを実行して、新しいディレクトリを作成します。
mkdir php-form-test
cd php-form-test
2. docker-compose.yml の作成
docker-compose.yml を作成し、以下の内容を記述します。
version: '3.8'
services:
php:
image: php:8.2-fpm
container_name: php-container
volumes:
- ./html:/var/www/html
nginx:
image: nginx:latest
container_name: nginx-container
ports:
- "8080:80"
volumes:
- ./html:/var/www/html
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- php
3. Nginx の設定ファイルを作成
nginx ディレクトリを作成し、default.conf を作成します。
mkdir nginx
server {
listen 80;
server_name localhost;
root /var/www/html;
index index.php index.html;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass php:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
4. PHP のフォームを作成
html ディレクトリを作成し、フォームを作る PHP ファイルを作成します。
mkdir html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>フォームのテスト</title>
</head>
<body>
<h2>フォームのテスト</h2>
<form method="POST" action="submit.php">
<label for="name">名前:</label>
<input type="text" id="name" name="name" required>
<br><br>
<input type="submit" value="送信">
</form>
</body>
</html>
<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$name = htmlspecialchars($_POST['name'], ENT_QUOTES, 'UTF-8');
echo "送信された名前: " . $name;
} else {
echo "POSTリクエストではありません。";
}
5. フォルダ構成の確認
ここまでで下記のフォルダ構成になっていればOKです。
$ tree php-form-test
php-form-test
├── docker-compose.yml
├── html
│ ├── index.php
│ └── submit.php
└── nginx
└── default.conf
2 directories, 4 files
6. Docker Compose を起動
php-form-testフォルダで以下のコマンドを実行して、コンテナを起動します。
docker-compose up -d
7. ブラウザで確認
まず、ブラウザで http://localhost:8080
にアクセスすると、フォームが表示されます。
フォームに名前を入力して送信すると、submit.php に POST データが送られ、その結果が画面に表示されます。
一方、名前を入力せずに送信ボタンを押すと、フロントエンド側のバリデーションチェックにより送信がブロックされます。
これは、以下のように input タグに required 属性を指定しているためです。
<input type="text" id="name" name="name" required>
試しに、required を削除して名前を入力せずに送信ボタンを押すと、フロントエンドのバリデーションチェックが働かず送信できることが確認できます。
8. バックエンドのバリデーションチェック
フロントエンド側でバリデーションチェックを実装しているため「これで問題ない」と思われるかもしれませんが、実際は簡単にチェックをすり抜けることが可能です。
たとえば、入力フォーム画面で F12 キーを押して開発者ツールを開きます。
開発者ツールの Elements タブで、対象の input タグを右クリックし「Edit as HTML」を選択します。
すると、input タグ全体が編集可能となるため、required="" の部分を削除し、適当な箇所をクリックして編集を確定します。
この状態で送信ボタンを押すと、先ほどのバリデーションチェックが働かずに送信できてしまいます。
ここで重要なのは、フロントエンドでどんなバリデーションチェックを実装しても、悪意のあるユーザーによって必ず突破されるという点です。
もちろん、ユーザビリティの観点からフロントエンドでのチェックは必要ですが、その前提に立ち、バックエンド側でも必ずバリデーションチェックを行う必要があります。
9. バックエンドのバリデーションチェックを実装する
それでは、バックエンド側で name が未入力の場合の処理を追加してみましょう。
以下は、submit.php の修正例です。
<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (empty($_POST['name'])) {
echo "名前は必須項目です";
} else {
$name = htmlspecialchars($_POST['name'], ENT_QUOTES, 'UTF-8');
echo "送信された名前: " . $name;
}
} else {
echo "POSTリクエストではありません。";
}
この例では、empty 関数を使って $_POST['name'] が空でないかを確認し、空の場合は「名前は必須項目です」というメッセージを出力するようにしています。
先ほどと同様に、フロントエンドのバリデーションチェックをすり抜ける手段で送信ボタンを押すと、今度は「送信された名前:」ではなく「名前は必須項目です」というメッセージが表示されることが確認できます。
これにより、バックエンド側でのバリデーションチェックが正しく実装されていることが確認できます。
実際の現場では、文字数制限や不正な文字が入力されていないかなど、さらに詳細なチェックが行われます。
また、今回の例では入力データの登録処理は実装していませんが、通常は入力されたデータをデータベースなどに登録する動作となります。
このような場合に不正なデータが登録されないよう、バックエンド側でのバリデーションチェックは非常に重要な処理です。
初学者の方はフロントエンドのみのバリデーションチェックに注目しがちですが、バックエンドのチェックも必須であることをしっかり認識していただければ幸いです。
10. コンテナの停止と削除
環境を停止・削除する場合は、以下のコマンドを実行してください。
docker-compose down -v
これで PHP のフォームと POST の動作を簡単に試せる環境が構築できます。
まとめ
$_POSTスーパーグローバル変数は、PHPにおいてPOSTリクエストを介して送信されたデータを扱う基本的な方法です。
安全なウェブアプリケーションを開発するためには、受け取ったデータの適切なバリデーションとエスケープ処理が不可欠です。