PHPでフォームの選択状態をセッションで保持する方法|チェックボックス・セレクトボックス・ラジオボタン


はじめに

前回の記事ではWeb制作でよく使うCSS小技をスニペット集としてまとめました。今回はPHPのセッションを使ってフォームの選択状態を保持する方法を解説します。「検索フィルターで絞り込んだ条件をページをまたいでも維持したい」「ページを戻ったときにラジオボタンの選択が消えていた」という場面はWeb制作でよく登場します。チェックボックス・セレクトボックス・ラジオボタンそれぞれの扱い方を丁寧に解説します。


1. セッションとは何か

1.1 セッションの基本概念

セッション(Session):

ユーザーがサイトを訪問している間
サーバー側にデータを一時的に保存する仕組み。

ブラウザを閉じると消える(デフォルト)。

例えるなら:
→ お店に入ったとき渡される番号札のようなもの
→ 番号(セッションID)をブラウザが持ち
  サーバー側に対応するデータが保存される

使う場面:
→ ログイン状態の保持
→ ショッピングカートの中身
→ フォームの入力内容の保持  ← 今回のテーマ
→ 検索フィルターの条件の保持

cookieとの違い:
→ cookie    :ブラウザ(クライアント側)に保存
→ session   :サーバー側に保存
→ sessionの方がセキュリティ面で安全

1.2 セッションの基本的な使い方

<?php
// ① セッションを開始する(すべてのページの先頭に書く)
session_start();

// ② データを保存する
$_SESSION['username'] = '山田太郎';
$_SESSION['age']      = 30;

// ③ データを取得する
echo $_SESSION['username']; // 山田太郎

// ④ データを削除する
unset( $_SESSION['username'] );

// ⑤ セッションをすべて破棄する(ログアウト時など)
session_destroy();
?>

<!--
    重要なルール:
    session_start() は
    → HTMLを出力する前に書く
    → すべてのページの一番上に書く
    → 1ページに1回だけ書く
-->

2. ラジオボタンの選択をセッションで保持する

2.1 HTMLフォーム

<?php session_start(); ?>
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>ラジオボタンのセッション保持</title>
</head>
<body>

<form method="post" action="confirm.php">

    <p>ご希望のプランを選択してください</p>

    <?php
    // セッションに保存された値を取得する
    // 保存されていない場合は空文字をデフォルト値にする
    $selected_plan = $_SESSION['plan'] ?? '';
    ?>

    <label>
        <input
            type="radio"
            name="plan"
            value="basic"
            <?php echo $selected_plan === 'basic' ? 'checked' : ''; ?>
        >
        ベーシックプラン(月額980円)
    </label>

    <label>
        <input
            type="radio"
            name="plan"
            value="standard"
            <?php echo $selected_plan === 'standard' ? 'checked' : ''; ?>
        >
        スタンダードプラン(月額1,980円)
    </label>

    <label>
        <input
            type="radio"
            name="plan"
            value="premium"
            <?php echo $selected_plan === 'premium' ? 'checked' : ''; ?>
        >
        プレミアムプラン(月額3,980円)
    </label>

    <button type="submit">次へ進む</button>

</form>

</body>
</html>

2.2 送信先のPHP処理

<?php
// confirm.php

session_start();

// POSTデータが送られてきた場合に処理する
if ( $_SERVER['REQUEST_METHOD'] === 'POST' ) {

    // ラジオボタンの値を取得してセッションに保存する
    // filter_input でセキュリティ対策をする
    $plan = filter_input( INPUT_POST, 'plan', FILTER_SANITIZE_SPECIAL_CHARS );

    // 許可する値のリスト(バリデーション)
    $allowed_plans = [ 'basic', 'standard', 'premium' ];

    if ( in_array( $plan, $allowed_plans, true ) ) {
        // 許可された値だけセッションに保存する
        $_SESSION['plan'] = $plan;
    }
}

// セッションから値を取得する
$selected_plan = $_SESSION['plan'] ?? '';

// プランのラベルを表示用に変換する
$plan_labels = [
    'basic'    => 'ベーシックプラン(月額980円)',
    'standard' => 'スタンダードプラン(月額1,980円)',
    'premium'  => 'プレミアムプラン(月額3,980円)',
];

$plan_label = $plan_labels[ $selected_plan ] ?? '未選択';
?>
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>確認ページ</title>
</head>
<body>

<h1>選択内容の確認</h1>

<p>選択プラン:<?php echo htmlspecialchars( $plan_label ); ?></p>

<!-- 戻るボタン(セッションが保持されているので選択が残る) -->
<a href="form.php">← 戻って変更する</a>

<form method="post" action="complete.php">
    <button type="submit">この内容で申し込む</button>
</form>

</body>
</html>

💡 htmlspecialchars() は必ず使う: セッションから取り出した値をHTMLに出力するときは htmlspecialchars() でエスケープしてXSS(クロスサイトスクリプティング)を防ぎます。


3. セレクトボックス(コンボボックス)の選択をセッションで保持する

3.1 HTMLフォーム

<?php session_start(); ?>
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>セレクトボックスのセッション保持</title>
</head>
<body>

<form method="post" action="search.php">

    <p>条件を選択して検索してください</p>

    <?php
    // セッションから値を取得する
    $selected_category = $_SESSION['category'] ?? '';
    $selected_price    = $_SESSION['price']    ?? '';
    $selected_sort     = $_SESSION['sort']     ?? 'newer';
    ?>

    <!-- カテゴリー -->
    <label for="category">カテゴリー</label>
    <select id="category" name="category">
        <option value="">すべて</option>
        <option value="web"    <?php echo $selected_category === 'web'    ? 'selected' : ''; ?>>Web制作</option>
        <option value="app"    <?php echo $selected_category === 'app'    ? 'selected' : ''; ?>>アプリ開発</option>
        <option value="design" <?php echo $selected_category === 'design' ? 'selected' : ''; ?>>デザイン</option>
        <option value="other"  <?php echo $selected_category === 'other'  ? 'selected' : ''; ?>>その他</option>
    </select>

    <!-- 価格帯 -->
    <label for="price">価格帯</label>
    <select id="price" name="price">
        <option value="">指定なし</option>
        <option value="under10k" <?php echo $selected_price === 'under10k' ? 'selected' : ''; ?>>1万円未満</option>
        <option value="10k-50k"  <?php echo $selected_price === '10k-50k'  ? 'selected' : ''; ?>>1万円〜5万円</option>
        <option value="over50k"  <?php echo $selected_price === 'over50k'  ? 'selected' : ''; ?>>5万円以上</option>
    </select>

    <!-- 並び順 -->
    <label for="sort">並び順</label>
    <select id="sort" name="sort">
        <option value="newer"   <?php echo $selected_sort === 'newer'   ? 'selected' : ''; ?>>新しい順</option>
        <option value="older"   <?php echo $selected_sort === 'older'   ? 'selected' : ''; ?>>古い順</option>
        <option value="popular" <?php echo $selected_sort === 'popular' ? 'selected' : ''; ?>>人気順</option>
    </select>

    <button type="submit">検索する</button>

</form>

</body>
</html>

3.2 送信先のPHP処理

<?php
// search.php

session_start();

if ( $_SERVER['REQUEST_METHOD'] === 'POST' ) {

    // 許可する値のリスト
    $allowed_categories = [ '', 'web', 'app', 'design', 'other' ];
    $allowed_prices     = [ '', 'under10k', '10k-50k', 'over50k' ];
    $allowed_sorts      = [ 'newer', 'older', 'popular' ];

    // カテゴリー
    $category = filter_input( INPUT_POST, 'category', FILTER_SANITIZE_SPECIAL_CHARS );
    if ( in_array( $category, $allowed_categories, true ) ) {
        $_SESSION['category'] = $category;
    }

    // 価格帯
    $price = filter_input( INPUT_POST, 'price', FILTER_SANITIZE_SPECIAL_CHARS );
    if ( in_array( $price, $allowed_prices, true ) ) {
        $_SESSION['price'] = $price;
    }

    // 並び順(デフォルト値を設定する)
    $sort = filter_input( INPUT_POST, 'sort', FILTER_SANITIZE_SPECIAL_CHARS );
    if ( in_array( $sort, $allowed_sorts, true ) ) {
        $_SESSION['sort'] = $sort;
    } else {
        $_SESSION['sort'] = 'newer';
    }
}

// セッションから検索条件を取得して検索処理を行う
$category = $_SESSION['category'] ?? '';
$price    = $_SESSION['price']    ?? '';
$sort     = $_SESSION['sort']     ?? 'newer';

/*
    ここで $category・$price・$sort を使って
    データベース検索などの処理を行う
*/
?>

4. チェックボックスの選択をセッションで保持する

4.1 チェックボックスの特殊な挙動

チェックボックスの注意点:

ラジオボタンやセレクトボックスと違い
チェックボックスは「チェックなし」のとき
POSTデータに何も送られない。

例:
チェックあり → $_POST['agree'] = 'on'(値が送られる)
チェックなし → $_POST['agree'] が存在しない(何も送られない)

→ isset() や null合体演算子(??)で
  存在チェックをする必要がある

複数のチェックボックスは配列で送る:
<input type="checkbox" name="tags[]" value="php">
<input type="checkbox" name="tags[]" value="css">
→ $_POST['tags'] = ['php', 'css'] のように配列で届く

4.2 単体のチェックボックス

<?php session_start(); ?>
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>チェックボックスのセッション保持</title>
</head>
<body>

<form method="post" action="result.php">

    <?php
    // セッションから値を取得する
    // チェックボックスは true/false で管理する
    $agreed       = $_SESSION['agreed']       ?? false;
    $subscribe    = $_SESSION['subscribe']    ?? false;
    ?>

    <!-- 利用規約への同意 -->
    <label>
        <input
            type="checkbox"
            name="agreed"
            value="1"
            <?php echo $agreed ? 'checked' : ''; ?>
        >
        利用規約に同意する
    </label>

    <!-- メルマガ購読 -->
    <label>
        <input
            type="checkbox"
            name="subscribe"
            value="1"
            <?php echo $subscribe ? 'checked' : ''; ?>
        >
        メールマガジンを購読する
    </label>

    <button type="submit">送信する</button>

</form>

</body>
</html>

4.3 複数チェックボックスの処理

<?php session_start(); ?>
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>複数チェックボックスのセッション保持</title>
</head>
<body>

<form method="post" action="filter.php">

    <p>興味のある分野を選択してください(複数選択可)</p>

    <?php
    // セッションから配列を取得する
    // 保存されていない場合は空配列をデフォルト値にする
    $selected_tags = $_SESSION['tags'] ?? [];
    ?>

    <?php
    // チェックボックスの選択肢を定義する
    $tag_options = [
        'php'        => 'PHP',
        'javascript' => 'JavaScript',
        'css'        => 'CSS',
        'wordpress'  => 'WordPress',
        'react'      => 'React',
        'python'     => 'Python',
    ];

    foreach ( $tag_options as $value => $label ) :
        // セッションの配列にこの値が含まれているか確認する
        $is_checked = in_array( $value, $selected_tags, true );
    ?>
        <label>
            <input
                type="checkbox"
                name="tags[]"
                value="<?php echo htmlspecialchars( $value ); ?>"
                <?php echo $is_checked ? 'checked' : ''; ?>
            >
            <?php echo htmlspecialchars( $label ); ?>
        </label>
    <?php endforeach; ?>

    <button type="submit">絞り込む</button>
    <a href="clear.php">条件をリセット</a>

</form>

</body>
</html>

4.4 送信先のPHP処理(チェックボックス)

<?php
// filter.php

session_start();

if ( $_SERVER['REQUEST_METHOD'] === 'POST' ) {

    // ===== 単体チェックボックスの処理 =====

    // チェックありなら true・なしなら false を保存する
    $_SESSION['agreed']    = isset( $_POST['agreed'] )    ? true : false;
    $_SESSION['subscribe'] = isset( $_POST['subscribe'] ) ? true : false;

    // ===== 複数チェックボックスの処理 =====

    // 許可する値のリスト
    $allowed_tags = [ 'php', 'javascript', 'css', 'wordpress', 'react', 'python' ];

    // POSTで送られてきた配列を取得する
    // チェックなしの場合は空配列になる
    $posted_tags = $_POST['tags'] ?? [];

    // 配列であることを確認してから処理する
    if ( is_array( $posted_tags ) ) {
        // 許可されている値だけを残す(バリデーション)
        $safe_tags = array_filter(
            $posted_tags,
            fn( $tag ) => in_array( $tag, $allowed_tags, true )
        );

        // 配列のインデックスを振り直してからセッションに保存する
        $_SESSION['tags'] = array_values( $safe_tags );
    } else {
        $_SESSION['tags'] = [];
    }
}

// セッションから値を確認する
$agreed    = $_SESSION['agreed']    ?? false;
$subscribe = $_SESSION['subscribe'] ?? false;
$tags      = $_SESSION['tags']      ?? [];
?>

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>選択結果</title>
</head>
<body>

<h1>選択内容</h1>

<p>利用規約:<?php echo $agreed ? '同意済み' : '未同意'; ?></p>
<p>メルマガ:<?php echo $subscribe ? '購読する' : '購読しない'; ?></p>

<p>興味のある分野:
    <?php if ( empty( $tags ) ) : ?>
        未選択
    <?php else : ?>
        <?php echo htmlspecialchars( implode( '・', $tags ) ); ?>
    <?php endif; ?>
</p>

<a href="form.php">← 戻って変更する</a>

</body>
</html>

5. セッションのリセット

5.1 条件をリセットするページ

<?php
// clear.php
// 検索条件・フォーム入力をリセットする

session_start();

// 特定のセッション変数だけ削除する
unset( $_SESSION['category'] );
unset( $_SESSION['price'] );
unset( $_SESSION['sort'] );
unset( $_SESSION['tags'] );
unset( $_SESSION['plan'] );
unset( $_SESSION['agreed'] );
unset( $_SESSION['subscribe'] );

// 元のページにリダイレクトする
header( 'Location: form.php' );
exit;
?>

6. まとめて管理する実践パターン

6.1 フォームの状態をまとめて保存・復元する

<?php
// functions.php(共通関数ファイル)

/**
 * フォームの選択状態をセッションに保存する
 */
function save_form_to_session( string $form_key, array $allowed_fields ): void {
    if ( $_SERVER['REQUEST_METHOD'] !== 'POST' ) return;

    foreach ( $allowed_fields as $field => $config ) {
        $type    = $config['type']    ?? 'string';
        $allowed = $config['allowed'] ?? null;

        switch ( $type ) {
            // チェックボックス(単体)
            case 'bool':
                $_SESSION[ $form_key ][ $field ] = isset( $_POST[ $field ] );
                break;

            // チェックボックス(複数)
            case 'array':
                $values = $_POST[ $field ] ?? [];
                if ( is_array( $values ) && $allowed !== null ) {
                    $_SESSION[ $form_key ][ $field ] = array_values(
                        array_filter(
                            $values,
                            fn( $v ) => in_array( $v, $allowed, true )
                        )
                    );
                } else {
                    $_SESSION[ $form_key ][ $field ] = [];
                }
                break;

            // ラジオボタン・セレクトボックス(単体の文字列)
            default:
                $value = filter_input( INPUT_POST, $field, FILTER_SANITIZE_SPECIAL_CHARS );
                if ( $allowed === null || in_array( $value, $allowed, true ) ) {
                    $_SESSION[ $form_key ][ $field ] = $value ?? '';
                }
                break;
        }
    }
}

/**
 * セッションからフォームの値を取得する
 */
function get_form_value( string $form_key, string $field, mixed $default = '' ): mixed {
    return $_SESSION[ $form_key ][ $field ] ?? $default;
}
<?php
// search.php(関数を使う例)

session_start();
require_once 'functions.php';

// フォームの定義
$form_config = [
    'category' => [
        'type'    => 'string',
        'allowed' => [ '', 'web', 'app', 'design', 'other' ],
    ],
    'price' => [
        'type'    => 'string',
        'allowed' => [ '', 'under10k', '10k-50k', 'over50k' ],
    ],
    'sort' => [
        'type'    => 'string',
        'allowed' => [ 'newer', 'older', 'popular' ],
    ],
    'tags' => [
        'type'    => 'array',
        'allowed' => [ 'php', 'javascript', 'css', 'wordpress', 'react' ],
    ],
    'subscribe' => [
        'type' => 'bool',
    ],
];

// POSTデータをセッションに保存する
save_form_to_session( 'search_form', $form_config );

// セッションから値を取得する
$category  = get_form_value( 'search_form', 'category',  '' );
$price     = get_form_value( 'search_form', 'price',     '' );
$sort      = get_form_value( 'search_form', 'sort',      'newer' );
$tags      = get_form_value( 'search_form', 'tags',      [] );
$subscribe = get_form_value( 'search_form', 'subscribe', false );
?>

7. 実践チェックリスト

✓ すべてのページの先頭に session_start() を書いているか(HTMLより前)

✓ ラジオボタン・セレクトボックスは $_SESSION['key'] ?? '' でデフォルト値を設定しているか

✓ チェックボックスは未チェック時にPOSTデータが送られないので isset() で存在確認しているか

✓ 複数チェックボックスは name="tags[]" のように [] を付けて配列で送っているか

✓ POSTで受け取った値を許可リスト($allowed)と照合してバリデーションしているか

✓ HTMLに出力するときは htmlspecialchars() でエスケープしてXSSを防いでいるか

✓ filter_input() でPOSTデータをサニタイズしてからセッションに保存しているか

✓ リセット用のページで unset() を使って特定のセッション変数だけ削除しているか


まとめ

今回はPHPのセッションを使ってフォームの選択状態を保持する方法を解説しました。ポイントをまとめると:

  • session_start() はHTMLより前・すべてのページの先頭に書く
  • セッションへの保存は $_SESSION['key'] = $value・取得は $_SESSION['key'] ?? デフォルト値
  • ラジオボタンとセレクトボックスは $_SESSION['key'] === 'value' ? 'checked' : '' でHTML側に反映する
  • チェックボックスはチェックなしのときPOSTデータが送られないので isset( $_POST['key'] ) で判定する
  • 複数チェックボックスは name="tags[]" で配列として送り・$_POST['tags'] ?? [] で受け取る
  • POSTで受け取った値は必ず許可リストと照合してバリデーションしてからセッションに保存する
  • HTMLへの出力は必ず htmlspecialchars() でエスケープしてXSSを防ぐ
  • セッションのリセットは unset() で特定のキーだけ削除してからリダイレクトする

次の記事では、PHPのファイル操作について解説します。ファイルの読み込み・書き込み・アップロードの実装方法をお届けします。お楽しみに!

コメント

タイトルとURLをコピーしました