広告

php select 選択状態を保持する

この記事は約17分で読めます。

phpでformを作っていて、google reCAPTCHA v3 を使うと、requiredを使って必須入力項目のチェックができません。(2分以内の送信に限ればrequiredが使えるけど・・・)

そこで、下記の流れで処理します。

submit(送信)
↓↓↓
サニタイズ
↓↓↓
エラー確認(必須項目の入力チェック)
↓↓↓
エラーがあるなら、入力画面に戻す

エラーがあるとき、入力画面に戻るとき、<input>要素なら、

<input type="text" name="zipcode" class="p-postal-code" size="8" maxlength="8" value="<?php if ( ! empty( $clean['zipcode'] ) ) { echo esc_attr( $clean['zipcode'] ); } ?>">

こんな風に、valueに書き込みます。

$clean['zipcode'] は、$_POST['zipcode']$_GET['zipcode']をサニタイズ処理したものです。esc_attr()はWordPressでHTML 要素の属性(alt, value, title, class など)の値に出力する文字をエスケープします。サニタイズ処理が2重になっている感じがありますが、esc_attr()は既にエスケープ処理されている場合はそのままですので、速度が遅くなりサーバーに負担がちょっとかかりますが問題ありません。

チェックボックスなら、こんな感じです。(input要素にcheckedを入れればOK)

<input id="ck1" type="checkbox" name="ck1" <?php if ( ! empty( $clean['ck1'] ) ) { echo 'checked'; } ?> >

select はちょっとコツがいる

ページ下部に追記した方法がおすすめです。

selectは、option要素にselectedを入れることで、選択状態を保持できます。

1つ1つにphpを入れて判定させても、良いのですが何個もあると大変です。

<select name="mi">
    <option value="なし" <?php if ( ! empty( $clean['mi'] ) ) { if ( 'なし' === $clean['mi'] ) { echo 'selected'; } } ?>>なし</option>
    <option value="あり" <?php if ( ! empty( $clean['mi'] ) ) { if ( 'あり' === $clean['mi'] ) { echo 'selected'; } } ?>>あり</option>
</select>

そこで、選択項目を連想配列にして、foreachを使って簡単に処理しちゃいましょう。

<select name="pref" class="p-region-id">
    <option value=""></option>
    <?php
        foreach ( $prefs as $key => $pref ) {
            if ( ! empty( $clean['pref'] ) ) {
                if ( $key === $clean['pref'] ) {
                    echo '<option value="' . $key . '" selected>' . $pref . '</option>';
                } else {
                    echo '<option value="' . $key . '">' . $pref . '</option>';
                }
            } else {
                echo '<option value="' . $key . '">' . $pref . '</option>';
            }
        }
    ?>
</select>

説明がちょっと難しいのですが・・・

$prefsはキーが数字、値が都道府県の連想配列です。

都道府県の連想配列 ページ下部にコピペ用データあります。

$prefs = array(
    '01'  => '北海道',
    '02'  => '青森県',
    '03'  => '岩手県',
・・・
    '47' => '沖縄県',
);

連想配列をforeachで回して、optionを作ります。

最初は、$clean['pref']があるなしをif ( ! empty( $clean['pref'] ) )で判断します。

これをしないとエラーが出ます。

送信ボタンを押すと、optionのvalueの値が、$_POST['pref']$_GET['pref']に入るので、サニタイズ処理して$clean['pref']

$clean['pref']が該当する(選択したもの)がforeachで回ってきたら、selectedがある方が出力されて、選択状態を保持できます。

説明が難しい・・・

ちなみに、郵便番号を入力すると自動で入力してくれるyubinbango.jsを使って、都道府県をプルダウン表示する目的で作っています。

yubinbango.jsを使う場合は、下記に補足あり

option要素のvalueと表示する文字列が同じなら、配列でもOKです。

なお、$clean はフォームをPOST送信した後、$_POSTの値をサニタイズした配列です。

<?php
$k_array = array(
    '責任者',
    'A士',
    'B師',
    'その他'
);
?>
<select name="k">
    <option value=""></option>
    <?php
    foreach ( $k_array as $value ) {
        if ( ! empty( $clean['k'] ) ) {
            if ( $value === $clean['k'] ) {
                echo '<option value="' . $value . '" selected>' . $value . '</option>';
            } else {
                echo '<option value="' . $value . '">' . $value . '</option>';
            }
        } else {
            echo '<option value="' . $value . '">' . $value . '</option>';
        }
    }
    ?>
</select>

WordPressで使ったので、if文がヨーダ記法になっています。ご注意ください。

都道府県のphp連想配列 コピペOK!

$prefs = array(
  '1'  => '北海道',
  '2'  => '青森県',
  '3'  => '岩手県',
  '4'  => '宮城県',
  '5'  => '秋田県',
  '6'  => '山形県',
  '7'  => '福島県',
  '8'  => '茨城県',
  '9'  => '栃木県',
  '10' => '群馬県',
  '11' => '埼玉県',
  '12' => '千葉県',
  '13' => '東京都',
  '14' => '神奈川県',
  '15' => '新潟県',
  '16' => '富山県',
  '17' => '石川県',
  '18' => '福井県',
  '19' => '山梨県',
  '20' => '長野県',
  '21' => '岐阜県',
  '22' => '静岡県',
  '23' => '愛知県',
  '24' => '三重県',
  '25' => '滋賀県',
  '26' => '京都府',
  '27' => '大阪府',
  '28' => '兵庫県',
  '29' => '奈良県',
  '30' => '和歌山県',
  '31' => '鳥取県',
  '32' => '島根県',
  '33' => '岡山県',
  '34' => '広島県',
  '35' => '山口県',
  '36' => '徳島県',
  '37' => '香川県',
  '38' => '愛媛県',
  '39' => '高知県',
  '40' => '福岡県',
  '41' => '佐賀県',
  '42' => '長崎県',
  '43' => '熊本県',
  '44' => '大分県',
  '45' => '宮崎県',
  '46' => '鹿児島県',
  '47' => '沖縄県',
);

yubinbango.js で 都道府県をselectを使う場合

以下、2024年2月追記

yubinbango.js を使わなければ上手くいったコードですが、残念なことにダメでした。

なお、$prefsは上にある都道府県のphp連想配列です。

<select name="prefectures" id="pref1" class="p-region-id">
  <option hidden>--</option>
  <?php
  foreach ($prefs as $key => $pref) {
    if (! empty($clean['prefectures']) && $key === $clean['prefectures']) {
      echo '<option value="' . $key . '" selected>' . $pref . '</option>';
    } else {
      echo '<option value="' . $key . '">' . $pref . '</option>';
    }
  }
  ?>
</select>

var_dumpで$clean[‘prefectures’]のデータと$keyのデータが型まで一致していることを確認したのですが、上手く動いてくれないことが発生しました。ーーー>型変換をしたらもしかしたらいける。(コードは下にあります)

yubinbango.js で使う、selectのクラス名”p-region-id”を消してみても同じでした。

そこで、jQureyを使って、selectさせてしまおうと考えて、みました。

phpのコード

<?php
if (!empty($clean['prefectures']) && '--' !== $clean['prefectures']) {
    echo '<span id="prefdata" style="display:none;" data-pref="' . $clean['prefectures'] . '">' . $clean['prefectures'] . '</span>' ;
}
?>
<select name="prefectures" id="pref1" class="p-region-id">
  <option hidden>--</option>
  <?php
  foreach ($prefs as $key => $pref) {
    echo '<option value="' . $key . '">' . $pref . '</option>';
  }
  ?>
</select>

jQureyのコード

$(document).ready(() => {
  // spanのdata-pref属性の値を取得
  const selectedPref = $('#prefdata').data('pref');
  console.log(selectedPref); // 確認用
  // select要素内のoption要素の中からvalue属性がselectedPrefと一致するものを選択状態にする
  $('#pref1').val(selectedPref);
});

通常のJavaScriptのコードの場合(未検証)

document.addEventListener('DOMContentLoaded', function() {
  // spanのdata-pref属性の値を取得
  const selectedPref = document.getElementById('prefdata').getAttribute('data-pref');
  console.log(selectedPref); // 確認用
  // select要素内のoption要素の中からvalue属性がselectedPrefと一致するものを選択状態にする
  document.getElementById('pref1').value = selectedPref;
});

強制的に型変換が必須かも?

別件で、同じようなことがあったので次のコードにしてみました。

yubinbango.js で 都道府県でselectを使う場合で型変換したコードです。

<select name="prefectures" id="pref1" class="p-region-id">
  <option hidden>--</option>
  <?php
  foreach ($prefs as $key => $pref) {
    $key = (string)$key;
    if (! empty($clean['prefectures']) && $key === $clean['prefectures']) {
      echo '<option value="' . $key . '" selected>' . $pref . '</option>';
    } else {
      echo '<option value="' . $key . '">' . $pref . '</option>';
    }
  }
  ?>
</select>

$days 1~31までの連想配列 キーと値が同じ

$days = array();
for ($i = 1; $i <= 31; $i++) {
    $days["$i"] = "$i";
}

selectを選択するコード

<select name="day" class="js-day">
  <option hidden>日</option>
  <?php
  $clean['day'] = (string)$clean['day'];
  foreach ($days as $key => $day) {
    $key = (string)$key;
    if (! empty($clean['day']) && $key === $clean['day']) {
        echo '<option value="' . $key . '"selected>' . $day . '</option>';
    } else {
      echo '<option value="' . $key . '">' . $day . '</option>';
    }
  }
  ?>
</select>

ご参考にしていただけたら幸いです。