PHPでのラジオボタンの実装方法について

採用はこちら

お問い合わせフォーム、申し込みフォーム、アンケートフォームなどでは、「複数の選択肢の中から1つだけ選んでもらう」項目を作りたい場面があります。

そのようなときに使うのが、ラジオボタンです。

PHPでラジオボタンを扱う場合、ラジオボタン自体はHTMLで作成し、送信された値をPHPで受け取って処理します。

基本的な流れは次の通りです。

HTMLでラジオボタンを作る
↓
フォームを送信する
↓
PHPで $_POST または $_GET を使って値を受け取る
↓
未選択や不正な値がないかチェックする
↓
必要に応じて画面表示やデータ保存を行う

ラジオボタンはHTMLだけでも表示できますが、実務ではPHP側でのバリデーションやエスケープ処理が重要になります。

目次

ラジオボタンの基本的な書き方

まずは、最も基本的なラジオボタンの例です。

<form method="post" action="">
  <p>性別を選択してください</p>

  <label>
    <input type="radio" name="gender" value="male">
    男性
  </label>

  <label>
    <input type="radio" name="gender" value="female">
    女性
  </label>

  <label>
    <input type="radio" name="gender" value="other">
    その他
  </label>

  <button type="submit">送信</button>
</form>

<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (isset($_POST['gender'])) {
        echo '選択された値:' . htmlspecialchars($_POST['gender'], ENT_QUOTES, 'UTF-8');
    } else {
        echo '性別が選択されていません。';
    }
}
?>

この例では、ユーザーが選択した値が $_POST['gender'] に入ります。

例えば「男性」を選んで送信した場合、PHP側では次の値を受け取ります。

$_POST['gender']; // male

画面上には「男性」と表示されていますが、PHPに送信されるのは value 属性に指定した male です。

ラジオボタンは同じnameでグループ化する

ラジオボタンで最も重要なのは、同じ選択グループにしたい項目には、同じ name 属性を指定することです。

<input type="radio" name="gender" value="male">
<input type="radio" name="gender" value="female">
<input type="radio" name="gender" value="other">

このように、すべて name="gender" にすると、3つの中から1つだけ選択できるようになります。

一方で、次のように name がバラバラだと、別々のグループとして扱われます。

<input type="radio" name="gender_male" value="male">
<input type="radio" name="gender_female" value="female">
<input type="radio" name="gender_other" value="other">

この場合、それぞれが別のラジオボタングループになるため、複数選択できてしまいます。

「1つの質問に対して1つだけ選ばせたい」場合は、必ず同じ name を指定しましょう。

PHPに送信されるのはvalueの値

ラジオボタンでは、ユーザーに表示されるテキストではなく、value 属性の値がPHPに送信されます。

例えば、次のようなラジオボタンがあるとします。

<label>
  <input type="radio" name="plan" value="basic">
  ベーシックプラン
</label>

画面上には「ベーシックプラン」と表示されます。

しかし、送信される値は次の文字列です。

basic

PHPでは、次のように受け取れます。

$plan = $_POST['plan'] ?? '';

この場合、$plan には basic が入ります。

つまり、ラジオボタンでは次のように考えると分かりやすいです。

表示名:ユーザーに見せる文字
value:PHPで受け取る値

例えば、次のように分けて管理します。

$plans = [
    'free' => '無料プラン',
    'basic' => 'ベーシックプラン',
    'premium' => 'プレミアムプラン',
];

このようにしておくと、データベースには basic のような内部値を保存し、画面では「ベーシックプラン」と表示できます。

valueを省略すると「on」が送信される

ラジオボタンでは、基本的に value 属性を必ず指定しましょう。

例えば、次のように value を省略したとします。

<input type="radio" name="plan">

このラジオボタンを選択して送信すると、PHP側では既定値として "on" が送信されます。

$_POST['plan']; // on

これでは、どの選択肢が選ばれたのか判別しにくくなります。

そのため、ラジオボタンには次のように value を明示するのが基本です。

<input type="radio" name="plan" value="basic">

特に、複数の選択肢を扱うフォームでは、必ず選択肢ごとに異なる value を設定しましょう。

初期選択を設定する方法

ページを開いた時点で、あらかじめ特定のラジオボタンを選択済みにしたい場合は、checked 属性を使います。

<label>
  <input type="radio" name="plan" value="free" checked>
  無料プラン
</label>

<label>
  <input type="radio" name="plan" value="basic">
  ベーシックプラン
</label>

<label>
  <input type="radio" name="plan" value="premium">
  プレミアムプラン
</label>

この場合、最初から「無料プラン」が選択された状態で表示されます。

ただし、初期値を設定するかどうかはフォームの目的によって判断しましょう。

例えば、検索フォームや並び替え条件であれば、初期値がある方が自然です。

新しい順
価格が安い順
人気順

一方で、アンケートや申し込みフォームのように、ユーザー自身に明確に選択してほしい場合は、初期選択を設定しない方がよいケースもあります。

送信後も選択状態を維持する方法

フォームで入力エラーがあった場合、再表示したときに選択内容が消えてしまうと、ユーザーにとって不便です。

そのため、送信された値に応じて checked を出し分けるのが一般的です。

<?php
$gender = $_POST['gender'] ?? '';
?>

<form method="post" action="">
  <p>性別を選択してください</p>

  <label>
    <input type="radio" name="gender" value="male"
      <?php if ($gender === 'male') echo 'checked'; ?>>
    男性
  </label>

  <label>
    <input type="radio" name="gender" value="female"
      <?php if ($gender === 'female') echo 'checked'; ?>>
    女性
  </label>

  <label>
    <input type="radio" name="gender" value="other"
      <?php if ($gender === 'other') echo 'checked'; ?>>
    その他
  </label>

  <button type="submit">送信</button>
</form>

ポイントは、最初に送信値を変数に入れておくことです。

$gender = $_POST['gender'] ?? '';

?? はNull合体演算子です。

$_POST['gender'] が存在すればその値を使い、存在しなければ空文字を入れます。

ラジオボタンが未選択の場合、$_POST['gender'] 自体が存在しないことがあります。

そのため、いきなり次のように書くと警告が出る可能性があります。

$gender = $_POST['gender'];

未選択の可能性がある項目では、次のように書くと安全です。

$gender = $_POST['gender'] ?? '';

選択肢は配列で管理すると便利

ラジオボタンの選択肢が少ない場合はHTMLに直接書いてもよいですが、実務では配列で管理する方が便利です。

<?php
$plans = [
    'free' => '無料プラン',
    'basic' => 'ベーシックプラン',
    'premium' => 'プレミアムプラン',
];

$selectedPlan = $_POST['plan'] ?? '';

function h($value) {
    return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
}
?>

<form method="post" action="">
  <p>プランを選択してください</p>

  <?php foreach ($plans as $value => $label): ?>
    <label>
      <input
        type="radio"
        name="plan"
        value="<?php echo h($value); ?>"
        <?php if ($selectedPlan === $value) echo 'checked'; ?>
      >
      <?php echo h($label); ?>
    </label>
    <br>
  <?php endforeach; ?>

  <button type="submit">送信</button>
</form>

このようにすると、選択肢を追加したい場合も配列を変更するだけで済みます。

$plans = [
    'free' => '無料プラン',
    'basic' => 'ベーシックプラン',
    'premium' => 'プレミアムプラン',
    'business' => 'ビジネスプラン',
];

HTMLを何か所も修正する必要がないため、保守しやすくなります。

また、配列で管理しておくと、バリデーションにも同じ配列を使えます。

ラジオボタンのバリデーション

ラジオボタンを使う場合、PHP側で必ずバリデーションを行いましょう。

主に確認すべき点は次の2つです。

未選択ではないか
想定外の値が送信されていないか

ラジオボタンは画面上では決められた選択肢しか選べません。

しかし、ブラウザの開発者ツールや直接リクエストを送る方法を使えば、想定外の値を送信することもできます。

例えば、本来は次の3つしか許可していないとします。

$plans = [
    'free' => '無料プラン',
    'basic' => 'ベーシックプラン',
    'premium' => 'プレミアムプラン',
];

しかし、外部から次のような値を送信される可能性もあります。

plan=admin

そのため、PHP側で「許可された値かどうか」を必ずチェックします。

<?php
$plans = [
    'free' => '無料プラン',
    'basic' => 'ベーシックプラン',
    'premium' => 'プレミアムプラン',
];

$selectedPlan = $_POST['plan'] ?? '';
$errors = [];
$message = '';

function h($value) {
    return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
}

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if ($selectedPlan === '') {
        $errors[] = 'プランを選択してください。';
    } elseif (!array_key_exists($selectedPlan, $plans)) {
        $errors[] = '不正な値が送信されました。';
    }

    if (empty($errors)) {
        $message = '選択されたプラン:' . $plans[$selectedPlan];
    }
}
?>

<form method="post" action="">
  <fieldset>
    <legend>プランを選択してください</legend>

    <?php foreach ($plans as $value => $label): ?>
      <label>
        <input
          type="radio"
          name="plan"
          value="<?php echo h($value); ?>"
          <?php if ($selectedPlan === $value) echo 'checked'; ?>
        >
        <?php echo h($label); ?>
      </label>
      <br>
    <?php endforeach; ?>
  </fieldset>

  <?php if (!empty($errors)): ?>
    <ul style="color: red;">
      <?php foreach ($errors as $error): ?>
        <li><?php echo h($error); ?></li>
      <?php endforeach; ?>
    </ul>
  <?php endif; ?>

  <button type="submit">送信</button>
</form>

<?php if ($message !== ''): ?>
  <p><?php echo h($message); ?></p>
<?php endif; ?>

この例では、次の部分で未選択をチェックしています。

if ($selectedPlan === '') {
    $errors[] = 'プランを選択してください。';
}

次に、許可されていない値をチェックしています。

elseif (!array_key_exists($selectedPlan, $plans)) {
    $errors[] = '不正な値が送信されました。';
}

$plans は連想配列なので、array_key_exists() を使うと、送信された値が配列のキーに存在するか確認できます。

requiredで未選択を防ぐ

HTML側で未選択を防ぎたい場合は、required 属性を使います。

<label>
  <input type="radio" name="plan" value="free" required>
  無料プラン
</label>

<label>
  <input type="radio" name="plan" value="basic">
  ベーシックプラン
</label>

<label>
  <input type="radio" name="plan" value="premium">
  プレミアムプラン
</label>

同じ name を持つラジオボタングループでは、グループ内の少なくとも1つに required が付いていれば、そのグループでいずれか1つの選択が必須になります。

また、次のようにすべての選択肢に required を付けても問題ありません。

<label>
  <input type="radio" name="plan" value="free" required>
  無料プラン
</label>

<label>
  <input type="radio" name="plan" value="basic" required>
  ベーシックプラン
</label>

<label>
  <input type="radio" name="plan" value="premium" required>
  プレミアムプラン
</label>

配列からラジオボタンを生成する場合は、すべてに required を出力する方が実装しやすいこともあります。

ただし、required はあくまでブラウザ側のチェックです。

HTMLはユーザー側で変更できるため、実務ではPHP側のバリデーションも必ず行いましょう。

GETでラジオボタンを使う場合

フォームの送信方法には、主に POSTGET があります。

検索条件や並び替え条件のように、URLに条件を含めたい場合は GET が向いています。

<?php
$sortOptions = [
    'new' => '新しい順',
    'popular' => '人気順',
    'price_low' => '価格が安い順',
];

$sort = $_GET['sort'] ?? 'new';

if (!array_key_exists($sort, $sortOptions)) {
    $sort = 'new';
}

function h($value) {
    return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
}
?>

<form method="get" action="">
  <fieldset>
    <legend>並び順</legend>

    <?php foreach ($sortOptions as $value => $label): ?>
      <label>
        <input
          type="radio"
          name="sort"
          value="<?php echo h($value); ?>"
          <?php if ($sort === $value) echo 'checked'; ?>
        >
        <?php echo h($label); ?>
      </label>
      <br>
    <?php endforeach; ?>
  </fieldset>

  <button type="submit">検索</button>
</form>

GETで送信すると、URLは次のようになります。

example.com/search.php?sort=popular

検索条件、絞り込み条件、並び替え条件などはGETが向いています。

一方で、問い合わせフォーム、会員登録、注文処理、ログインフォームなどはPOSTを使うのが一般的です。

複数のラジオボタングループを使う場合

1つのフォーム内に複数のラジオボタングループを設置することもできます。

その場合は、グループごとに異なる name を指定します。

<p>性別</p>
<label>
  <input type="radio" name="gender" value="male">
  男性
</label>
<label>
  <input type="radio" name="gender" value="female">
  女性
</label>
<label>
  <input type="radio" name="gender" value="other">
  その他
</label>

<p>会員種別</p>
<label>
  <input type="radio" name="member_type" value="normal">
  通常会員
</label>
<label>
  <input type="radio" name="member_type" value="premium">
  プレミアム会員
</label>

PHP側では、それぞれ別のキーで受け取ります。

$gender = $_POST['gender'] ?? '';
$memberType = $_POST['member_type'] ?? '';

同じグループにしたいものは同じ name、別グループにしたいものは別の name にするのが基本です。

確認画面付きフォームでラジオボタンを使う例

お問い合わせフォームや申し込みフォームでは、次のような流れにすることがあります。

入力画面
↓
確認画面
↓
完了画面

確認画面付きフォームでは、「確認する」「戻る」「送信する」の処理を分ける必要があります。

単純に同じページへPOSTするだけだと、「戻る」ボタンを押しても再び確認画面が表示されることがあります。

そのため、ボタンの namevalue で処理を分岐すると分かりやすくなります。

<?php
$plans = [
    'free' => '無料プラン',
    'basic' => 'ベーシックプラン',
    'premium' => 'プレミアムプラン',
];

$selectedPlan = $_POST['plan'] ?? '';
$action = $_POST['action'] ?? '';
$errors = [];

function h($value) {
    return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
}

if ($_SERVER['REQUEST_METHOD'] === 'POST' && $action === 'confirm') {
    if ($selectedPlan === '') {
        $errors[] = 'プランを選択してください。';
    } elseif (!array_key_exists($selectedPlan, $plans)) {
        $errors[] = '不正な値が送信されました。';
    }

    if (empty($errors)) {
        ?>
        <h2>確認画面</h2>

        <p>選択したプラン:<?php echo h($plans[$selectedPlan]); ?></p>

        <form method="post" action="complete.php">
          <input type="hidden" name="plan" value="<?php echo h($selectedPlan); ?>">
          <button type="submit">送信する</button>
        </form>

        <form method="post" action="">
          <input type="hidden" name="plan" value="<?php echo h($selectedPlan); ?>">
          <button type="submit" name="action" value="back">戻る</button>
        </form>
        <?php
        exit;
    }
}
?>

<form method="post" action="">
  <fieldset>
    <legend>プランを選択してください</legend>

    <?php foreach ($plans as $value => $label): ?>
      <label>
        <input
          type="radio"
          name="plan"
          value="<?php echo h($value); ?>"
          <?php if ($selectedPlan === $value) echo 'checked'; ?>
        >
        <?php echo h($label); ?>
      </label>
      <br>
    <?php endforeach; ?>
  </fieldset>

  <?php if (!empty($errors)): ?>
    <ul style="color: red;">
      <?php foreach ($errors as $error): ?>
        <li><?php echo h($error); ?></li>
      <?php endforeach; ?>
    </ul>
  <?php endif; ?>

  <button type="submit" name="action" value="confirm">確認する</button>
</form>

確認画面へ進むボタンには、次のように指定しています。

<button type="submit" name="action" value="confirm">確認する</button>

そしてPHP側で、$action === 'confirm' のときだけ確認画面を表示します。

if ($_SERVER['REQUEST_METHOD'] === 'POST' && $action === 'confirm') {
    // 確認画面の処理
}

戻るボタンを押した場合は action=back になるため、確認画面の条件に入らず、入力画面が表示されます。

hiddenの値も信用しない

確認画面では、選択された値を次の画面へ渡すために hidden を使うことがあります。

<input type="hidden" name="plan" value="basic">

ただし、hidden の値もユーザー側で変更できます。

そのため、完了画面側でも再度バリデーションが必要です。

例えば、complete.php 側でも次のようにチェックします。

<?php
$plans = [
    'free' => '無料プラン',
    'basic' => 'ベーシックプラン',
    'premium' => 'プレミアムプラン',
];

$selectedPlan = $_POST['plan'] ?? '';

if ($selectedPlan === '') {
    exit('プランが選択されていません。');
}

if (!array_key_exists($selectedPlan, $plans)) {
    exit('不正な値が送信されました。');
}

echo '送信が完了しました。';

入力画面で一度チェックしたからといって、完了画面でのチェックを省略しないようにしましょう。

実務ではCSRF対策も行う

実務でフォームを作る場合は、CSRF対策も考える必要があります。

CSRFとは、ユーザーが意図しないリクエストを外部サイトから送信させられる攻撃のことです。

問い合わせフォーム、会員登録フォーム、注文フォーム、管理画面の設定フォームなどでは、CSRFトークンを使って対策するのが一般的です。

簡単な例を紹介します。

まず、フォームを表示する前にセッションを開始し、トークンを作成します。

<?php
session_start();

if (empty($_SESSION['csrf_token'])) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}

function h($value) {
    return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
}
?>

フォームには、トークンをhiddenで埋め込みます。

<input type="hidden" name="csrf_token" value="<?php echo h($_SESSION['csrf_token']); ?>">

送信時には、セッションに保存したトークンと送信されたトークンを比較します。

if (
    empty($_POST['csrf_token']) ||
    empty($_SESSION['csrf_token']) ||
    !hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])
) {
    exit('不正な送信です。');
}

ラジオボタンそのものの実装には必須ではありませんが、フォーム全体を安全に運用するためには重要な考え方です。

ラジオボタンの値をデータベースに保存する場合

ラジオボタンで選択された値をデータベースに保存する場合は、基本的に value の値を保存します。

例えば、次のような選択肢があるとします。

$plans = [
    'free' => '無料プラン',
    'basic' => 'ベーシックプラン',
    'premium' => 'プレミアムプラン',
];

この場合、データベースには次のような値を保存します。

basic

画面に表示するときは、配列を使ってラベルに変換します。

echo $plans[$planFromDatabase] ?? '不明なプラン';

このように、保存値と表示名を分けておくと、後から表示名を変更しやすくなります。

例えば、表示名を「ベーシックプラン」から「スタンダードプラン」に変更したい場合でも、データベースの値は basic のままで済みます。

PDOで保存する例

PHPでMySQLなどのデータベースに保存する場合は、PDOを使えます。

以下は、選択されたプランを保存する簡単な例です。

<?php
$plans = [
    'free' => '無料プラン',
    'basic' => 'ベーシックプラン',
    'premium' => 'プレミアムプラン',
];

$selectedPlan = $_POST['plan'] ?? '';
$errors = [];

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if ($selectedPlan === '') {
        $errors[] = 'プランを選択してください。';
    } elseif (!array_key_exists($selectedPlan, $plans)) {
        $errors[] = '不正な値が送信されました。';
    }

    if (empty($errors)) {
        try {
            $pdo = new PDO(
                'mysql:host=localhost;dbname=test_db;charset=utf8mb4',
                'root',
                'password',
                [
                    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
                ]
            );

            $stmt = $pdo->prepare('INSERT INTO users (plan) VALUES (:plan)');
            $stmt->bindValue(':plan', $selectedPlan, PDO::PARAM_STR);
            $stmt->execute();

            echo '保存しました。';
        } catch (PDOException $e) {
            echo 'データベース処理でエラーが発生しました。';
        }
    }
}
?>

重要なのは、SQLに直接値を埋め込まないことです。

避けたい書き方は次のようなものです。

$sql = "INSERT INTO users (plan) VALUES ('$selectedPlan')";

このような書き方は、SQLインジェクションのリスクがあります。

安全に保存するには、次のようにプリペアドステートメントを使います。

$stmt = $pdo->prepare('INSERT INTO users (plan) VALUES (:plan)');
$stmt->bindValue(':plan', $selectedPlan, PDO::PARAM_STR);
$stmt->execute();

また、実際の運用では、データベースの接続情報をPHPファイルに直接書くのではなく、環境変数や設定ファイルで管理するのが一般的です。

出力時はhtmlspecialcharsでエスケープする

フォームで受け取った値や、配列に入っているラベルを画面に出力するときは、htmlspecialchars() を使ってエスケープしましょう。

echo htmlspecialchars($value, ENT_QUOTES, 'UTF-8');

何度も書くのが面倒な場合は、次のように関数化しておくと便利です。

function h($value) {
    return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
}

使うときは次のようにします。

echo h($label);

HTML属性の中に出す場合も、エスケープが必要です。

value="<?php echo h($value); ?>"

ユーザーが送信した値をそのまま画面に出すと、XSSの原因になる可能性があります。

悪い例は次の通りです。

echo $_POST['plan'];

安全に出力するなら、次のようにします。

echo h($_POST['plan'] ?? '');

ただし、実務ではエスケープだけでなく、許可された値かどうかのチェックも行いましょう。

fieldsetとlegendを使うと分かりやすい

ラジオボタンのグループには、fieldsetlegend を使うとフォームの意味が分かりやすくなります。

<fieldset>
  <legend>お問い合わせ種別</legend>

  <label>
    <input type="radio" name="contact_type" value="question">
    質問
  </label>

  <label>
    <input type="radio" name="contact_type" value="estimate">
    見積もり依頼
  </label>
</fieldset>

fieldset はフォーム項目をグループ化するための要素です。

legend はそのグループの見出しになります。

ラジオボタンのように、複数の選択肢が1つの意味を持つ場合は、fieldsetlegend を使うと、HTMLの構造としても分かりやすくなります。

WordPressでラジオボタンを実装する場合

WordPressのテーマやプラグインでラジオボタンを扱う場合も、基本的な考え方は同じです。

ただし、WordPressでは専用の関数を使うと安全で書きやすくなります。

<?php
$selected = $_POST['plan'] ?? '';

$plans = [
    'free' => '無料プラン',
    'basic' => 'ベーシックプラン',
    'premium' => 'プレミアムプラン',
];
?>

<form method="post">
  <fieldset>
    <legend>プランを選択してください</legend>

    <?php foreach ($plans as $value => $label): ?>
      <label>
        <input
          type="radio"
          name="plan"
          value="<?php echo esc_attr($value); ?>"
          <?php checked($selected, $value); ?>
        >
        <?php echo esc_html($label); ?>
      </label>
      <br>
    <?php endforeach; ?>
  </fieldset>

  <button type="submit">送信</button>
</form>

WordPressでは、選択状態の出力に checked() が使えます。

<?php checked($selected, $value); ?>

$selected$value が一致した場合、自動的に checked="checked" を出力してくれます。

また、属性値には esc_attr()、テキストには esc_html() を使うのが基本です。

esc_attr($value);
esc_html($label);

WordPress内でフォームを作る場合は、通常の htmlspecialchars() よりもWordPressのエスケープ関数を使う方が自然です。

ラジオボタンとチェックボックスの違い

ラジオボタンとチェックボックスは似ていますが、用途が異なります。

項目ラジオボタンチェックボックス
選択数1つだけ選択複数選択できる
主な用途支払い方法、配送方法、プラン選択興味のある項目、複数カテゴリ、同意項目
name属性同じグループは同じname複数選択では配列名にすることが多い
PHPでの受け取り$_POST['plan']$_POST['categories'] など

ラジオボタンは、選択肢の中から1つだけ選ばせたい場合に使います。

例えば、次のような項目に向いています。

支払い方法
配送方法
会員プラン
問い合わせ種別
年代
満足度
はい・いいえ

一方で、複数選択を許可したい場合は、ラジオボタンではなくチェックボックスを使います。

よくあるミス

nameがバラバラになっている

ラジオボタンでよくあるミスが、同じグループにしたい選択肢の name をバラバラにしてしまうことです。

悪い例です。

<input type="radio" name="plan_free" value="free">
<input type="radio" name="plan_basic" value="basic">
<input type="radio" name="plan_premium" value="premium">

これでは、それぞれ別のグループとして扱われます。

正しくは、同じ name にします。

<input type="radio" name="plan" value="free">
<input type="radio" name="plan" value="basic">
<input type="radio" name="plan" value="premium">

valueを書き忘れている

value を省略すると、選択時に "on" が送信されます。

悪い例です。

<input type="radio" name="plan">

正しくは、選択肢ごとに value を指定します。

<input type="radio" name="plan" value="basic">

未選択時の処理をしていない

ラジオボタンが未選択の場合、$_POST['plan'] が存在しないことがあります。

悪い例です。

$plan = $_POST['plan'];

正しくは、次のようにします。

$plan = $_POST['plan'] ?? '';

または、isset() を使って確認します。

if (isset($_POST['plan'])) {
    $plan = $_POST['plan'];
} else {
    $plan = '';
}

checkedの比較で代入している

checked を出し分けるときに、比較ではなく代入を書いてしまうミスがあります。

悪い例です。

<?php if ($selectedPlan = 'basic') echo 'checked'; ?>

これは $selectedPlan'basic' を代入しているだけです。

正しくは、比較演算子を使います。

<?php if ($selectedPlan === 'basic') echo 'checked'; ?>

PHPでは、値と型を厳密に比較する === を使うと安全です。

HTML側の値だけを信用している

ラジオボタンは、画面上では決められた値しか選べないように見えます。

しかし、実際には送信値を改変することができます。

そのため、PHP側では必ず許可値をチェックしましょう。

$allowedPlans = ['free', 'basic', 'premium'];

if (!in_array($selectedPlan, $allowedPlans, true)) {
    $errors[] = '不正な値です。';
}

連想配列で選択肢を管理している場合は、array_key_exists() が便利です。

if (!array_key_exists($selectedPlan, $plans)) {
    $errors[] = '不正な値です。';
}

実務向けの完成サンプル

最後に、ラジオボタンの基本をまとめた完成サンプルを紹介します。

お問い合わせ種別を選択するフォームです。

<?php
$contactTypes = [
    'question' => '質問',
    'estimate' => '見積もり依頼',
    'support' => 'サポート',
    'other' => 'その他',
];

$contactType = $_POST['contact_type'] ?? '';
$errors = [];
$result = '';

function h($value) {
    return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
}

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if ($contactType === '') {
        $errors[] = 'お問い合わせ種別を選択してください。';
    } elseif (!array_key_exists($contactType, $contactTypes)) {
        $errors[] = 'お問い合わせ種別の値が正しくありません。';
    }

    if (empty($errors)) {
        $result = 'お問い合わせ種別:' . $contactTypes[$contactType];
    }
}
?>

<form method="post" action="">
  <fieldset>
    <legend>お問い合わせ種別</legend>

    <?php foreach ($contactTypes as $value => $label): ?>
      <label>
        <input
          type="radio"
          name="contact_type"
          value="<?php echo h($value); ?>"
          <?php if ($contactType === $value) echo 'checked'; ?>
          required
        >
        <?php echo h($label); ?>
      </label>
      <br>
    <?php endforeach; ?>
  </fieldset>

  <?php if (!empty($errors)): ?>
    <ul style="color: red;">
      <?php foreach ($errors as $error): ?>
        <li><?php echo h($error); ?></li>
      <?php endforeach; ?>
    </ul>
  <?php endif; ?>

  <button type="submit">送信</button>
</form>

<?php if ($result !== ''): ?>
  <p><?php echo h($result); ?></p>
<?php endif; ?>

このサンプルでは、次のポイントを押さえています。

選択肢を配列で管理している
送信後も選択状態を維持している
未選択チェックをしている
不正な値のチェックをしている
requiredでブラウザ側の未選択も防いでいる
htmlspecialcharsで出力をエスケープしている
fieldsetとlegendでグループ化している

基本的なフォームであれば、この形をベースにすると実装しやすいです。

まとめ

PHPでラジオボタンを実装する場合は、HTMLでラジオボタンを作り、PHPで送信された値を受け取ります。

基本の形は次の通りです。

<input type="radio" name="plan" value="basic">

PHP側では次のように受け取ります。

$plan = $_POST['plan'] ?? '';

実務では、単に値を受け取るだけでなく、次の点を意識しましょう。

同じグループのラジオボタンは同じnameにする
PHPに送信されるのはvalueの値
valueを省略するとonが送信される
未選択時は$_POSTにキーが存在しない場合がある
送信後も選択状態を維持するにはcheckedを出し分ける
requiredはブラウザ側の補助として使う
PHP側でも必ずバリデーションする
想定外の値が送信されていないか確認する
出力時はhtmlspecialcharsでエスケープする
確認画面や完了画面でも再チェックする
実務ではCSRF対策も検討する

特に重要なのは、HTML側のラジオボタンを信用しすぎないことです。

ユーザーは通常の画面上では決められた値しか選べませんが、送信値は改変できます。

そのため、PHP側で「未選択ではないか」「許可された値か」を確認することが大切です。

ラジオボタンの実装では、選択肢を配列で管理し、その配列を表示・バリデーション・表示ラベル変換に使い回すと、保守しやすく安全なコードになります。

以上、PHPでのラジオボタンの実装方法についてでした。

最後までお読みいただき、ありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次