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を使って、都道府県をプルダウン表示する目的で作っています。
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>
都道府県の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;
});
強制的に型変換が必須かも?
別件で、同じようなことがあったので次のコードにしてみました。
<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>
ご参考にしていただけたら幸いです。