応募フォーム的なものを作らなければならなくなったので、楽できないかなあ?
と調べたら、簡単! シンプル! Contact Form 7がいいみたい。
でも、シンプルすぎる故の落とし穴にはまってカスタマイズしまくるハメになったというお話です。
目次
AjaxZip3を使って住所検索を簡単に実装
応募者情報の項目としてありがちな住所検索はAjaxZip3と組み合わせればさくっと実装完了。
やるじゃん! 簡単!
1 2 3 4 5 6 7 8 9 |
<script type="text/javascript" src="https://ajaxzip3.github.io/ajaxzip3.js" charset="UTF-8"></script> 氏名:[text* name] しめい:[text* namekana] 郵便番号:[text* zip1 size:3 minlength:3 maxlength:3]-[text* zip2 size:4 minlength:4 maxlength:4] <input type="button" onclick="AjaxZip3.zip2addr('zip1','zip2','prefecture','city');" value="住所検索" /> 都道府県:[select* prefecture "北海道" "青森県" "岩手県" "宮城県" "秋田県" "山形県" "福島県" "茨城県" "栃木県" "群馬県" "埼玉県" "千葉県" "東京都" "神奈川県" "新潟県" "富山県" "石川県" "福井県" "山梨県" "長野県" "岐阜県" "静岡県" "愛知県" "三重県" "滋賀県" "京都府" "大阪府" "兵庫県" "奈良県" "和歌山県" "鳥取県" "島根県" "岡山県" "広島県" "山口県" "徳島県" "香川県" "愛媛県" "高知県" "福岡県" "佐賀県" "長崎県" "熊本県" "大分県" "宮崎県" "鹿児島県" "沖縄県"] 市区町村:[text* city] 電話番号:[tel* tel] [submit] |
落とし穴1:バリデーション諸々がイマイチすぎる・・・
フォームができたぞ!
telフィールドがあるということは、その辺の書式チェック・補正もバッチリか!
ということで目をキラキラしながら入力、送信・・・っと!
次におまるくんが目にしたのは悲しい現実でした。
お、おう・・・!
全角入力したからな!!
これ、前時代的なフォームのやつや・・・。
埋め立て作業1:書式チェック・補正機能を追加しよう!
この時点で既に沸いてきた、もうベタ書きでフォーム作った方が早いやん・・・。
という気持ちに蓋をして。
書式補正はクライアントサイドでかけつつ、自前の書式チェックを付け加えるなら、こうかなぁの実装をします。
class属性を書式補正のターゲットにしつつ、書式チェックの判断基準にも使うよ!
コントロールごとにadd_filterしてたら面倒でやってられなくなるので、wpcf7_validateにフックしてなるべく後の追加の手間を省く感じに仕上げます。
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 |
氏名:[text* name class:wide] しめい:[text* namekana class:hiragana] 郵便番号:[text* zip1 class:digit size:3]-[text* zip2 class:digit size:4]<input type="button" onclick="AjaxZip3.zip2addr('zip1','zip2','prefecture','city');" value="住所検索" /> 都道府県:[select* prefecture "北海道" "青森県" "岩手県" "宮城県" "秋田県" "山形県" "福島県" "茨城県" "栃木県" "群馬県" "埼玉県" "千葉県" "東京都" "神奈川県" "新潟県" "富山県" "石川県" "福井県" "山梨県" "長野県" "岐阜県" "静岡県" "愛知県" "三重県" "滋賀県" "京都府" "大阪府" "兵庫県" "奈良県" "和歌山県" "鳥取県" "島根県" "岡山県" "広島県" "山口県" "徳島県" "香川県" "愛媛県" "高知県" "福岡県" "佐賀県" "長崎県" "熊本県" "大分県" "宮崎県" "鹿児島県" "沖縄県"] 市区町村:[text* city class:wide] 電話番号:[tel* tel class:half] [submit] <script type="text/javascript" src="https://ajaxzip3.github.io/ajaxzip3.js" charset="UTF-8"></script> <script type="text/javascript"> (function($){ function toHiragana(e) { e.val(e.val().replace(/[\u30a1-\u30f6]/g, function(m) { return String.fromCharCode(m.charCodeAt(0) - 0x60); })); } function toKatakana(e) { e.val(e.val().replace(/[\u3041-\u3096]/g, function(m) { return String.fromCharCode(m.charCodeAt(0) + 0x60); })); } function toHalf(e) { e.val(e.val().replace(/[!-~]/g, function(m){ return String.fromCharCode(m.charCodeAt(0)-0xFEE0) })); } function toWide(e) { e.val(e.val().replace(/[!-~]/g, function(m){ return String.fromCharCode(m.charCodeAt(0)+0xFEE0) })); } $('.wpcf7-form-control.digit').blur(function() {toHalf($(this))}); $('.wpcf7-form-control.hiragana').blur(function() {toHiragana($(this))}); $('.wpcf7-form-control.katakana').blur(function() {toKatakana($(this))}); $('.wpcf7-form-control.half').blur(function() {toHalf($(this))}); $('.wpcf7-form-control.wide').blur(function() {toWide($(this))}); })(jQuery); </script> |
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 48 49 50 51 52 53 54 55 56 57 58 59 |
// Contact form 7 書式チェックの拡張 function wpcf7_validation_format($result, $tags) { foreach ($tags as $tag) { if (!isset($tag['options'])) { continue; } $class = ''; // class: 属性の値を取得 foreach ($tag['options'] as $option) { $option = explode(':', $option); if ($option[0] == 'class') { $class = $option[1]; break; } } if (!$class) { continue; } $name = $tag['name']; if (isset($_POST[$name])) { $value = $_POST[$name]; } $error = ''; mb_regex_encoding('UTF-8'); // class属性ごとに書式チェック振り分け switch($class) { case 'hiragana': if (!preg_match('/^[ぁ-ん]+$/u', $value)) { $error = 'ひらがなのみの入力です'; } break; case 'katakana': if (!preg_match('/^[ァ-ヶー]+$/u', $value)) { $error = 'カタカナのみの入力です'; } break; case 'digit': if (!preg_match('/^[0-9]+$/u', $value)) { $error = '数字のみの入力です'; } break; case 'half': if (mb_strwidth($value) != mb_strlen($value)) { $error = '半角のみの入力です'; } break; case 'wide': if (mb_strwidth($value) != mb_strlen($value) * 2) { $error = '全角のみの入力です'; } break; } $result->invalidate($tag, $error); } return $result; } // フィルターフック add_filter('wpcf7_validate', 'wpcf7_validation_format', 11, 2); |
落とし穴2:エラーメッセージが入力項目をman2manでバッチリマーク
やったー! ひらがなやら半角に補正がかかるし、書式のチェックもちゃんとできるようになったよー。
ほら、見て見て! エラーも表示されてるし!
郵便番号なんて2つに分断されるぐらいにでかでかとぉぉぉう・・・。
あ、あかん・・・。
埋め立て作業2:エラーメッセージの取り纏めができるようにしよう!
どうやらリファレンスに示されている規定のclassやsizeといった属性だけでなく、勝手属性をタグ内に記述すれば、$tag[‘options’]として取得できるようなので、
勝手属性 mergeerror を追加して、「ここのエラーはこっちに一括表示してね」の指定ができるようにしてみます。
テンプレートのzip1に、エラーが出たらzip2に表示してよ を指定。
1 2 3 4 5 6 7 8 |
氏名:[text* name class:wide] しめい:[text* namekana class:hiragana] 郵便番号:[text* zip1 class:digit mergeerror:zip2 minlength:3 maxlength:3 size:3]-[text* zip2 class:digit maxlength:4 minlength:4 size:4]<input type="button" onclick="AjaxZip3.zip2addr('zip1','zip2','prefecture','city');" value="住所検索" /> 都道府県:[select* prefecture "北海道" "青森県" "岩手県" "宮城県" "秋田県" "山形県" "福島県" "茨城県" "栃木県" "群馬県" "埼玉県" "千葉県" "東京都" "神奈川県" "新潟県" "富山県" "石川県" "福井県" "山梨県" "長野県" "岐阜県" "静岡県" "愛知県" "三重県" "滋賀県" "京都府" "大阪府" "兵庫県" "奈良県" "和歌山県" "鳥取県" "島根県" "岡山県" "広島県" "山口県" "徳島県" "香川県" "愛媛県" "高知県" "福岡県" "佐賀県" "長崎県" "熊本県" "大分県" "宮崎県" "鹿児島県" "沖縄県"] 市区町村:[text* city class:wide] 電話番号:[tel* tel] [submit] |
WPCF7_Validation::$containerや、 $invalid_fields[‘idref’]が何をしてるのか実は追いきれていないけれど、置き換えてもたぶん問題ないんじゃね!?
という適当な推測の元、全てのエラーチェックが出そろった頃合いを見て、エラー内容の取り纏め結果を newで再構築しておきかえてしまうという若干強引な手段で対応してみました。
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 |
// Contact form 7 エラーメッセージをひとまとめにする function wpcf7_validation_mergeerror($result, $tags) { $result = $result->get_invalid_fields(); $newreasons = array(); foreach ($tags as $tag) { $name = $tag['name']; if (!isset($result[$name])) { continue; } $mergeerror= ''; // mergeerror: 属性の値を取得 if (isset($tag['options'])) { foreach ($tag['options'] as $option) { $option = explode(':', $option); if ($option[0] == 'mergeerror') { $mergeerror = $option[1]; break; } } } $mergeerror= ($mergeerror) ? $mergeerror: $name; // 一番最初のエラーだけ表示 if (!isset($newreasons[$mergeerror])) { $newreasons[$mergeerror] = $result[$name]['reason']; } } // 再度定義 $newresult = new WPCF7_Validation(); foreach ($newreasons as $name => $reason) { $newresult->invalidate($name, $reason); } return $newresult; } // フィルターフック add_filter('wpcf7_validate', 'wpcf7_validation_mergeerror', 99, 2); |
落とし穴3 : セットと言えば、同一入力チェックは?
郵便番号のセット項目エラーが纏まったぜ!!
そういえば、複数入力項目のセット・・・と言えば、
タイプミス防止のために、
メールアドレスをもう一度入力してください。
とか、パスワードをもう一度入力してください。
なんてのがよくありますよね。
そして、簡単! シンプル! だと、当然そういうの、ない? ですよねー。
埋め立て作業3 : 同一入力チェックな複数項目チェックを実装しよう
とりあえず定番らしいメールアドレスの入力確認かな?
を実装してみます。
タグの種別単位でチェックを追加するのもいいですけど、
似たようなチェックで都度、add_filterしてコードを増やしていくのは嫌なのでエラーの取り纏め同様、独自の属性を作って対応することにします。
confirm:グループ名 を指定すると、同一グループ名の入力値が一致しないとエラー! の実装です。
1 2 |
メールアドレス[email* email class:half confirm:email mergeerror:emailconfirm] メールアドレス(確認)[email* emailconfirm class:half confirm:email] |
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 |
// Contact form 7 同一入力確認チェック function wpcf7_validation_confirm($result, $tags) { $confirmvalue = array(); foreach ($tags as $tag) { if (!isset($tag['options'])) { continue; } $confirmkey = ''; // confirm: 属性の値を取得 foreach ($tag['options'] as $option) { $option = explode(':', $option); if ($option[0] == 'confirm') { $confirmkey = $option[1]; break; } } if (!$confirmkey) { continue; } $name = $tag['name']; if (isset($_POST[$name])) { $value = $_POST[$name]; } // 値が一致するかチェック if (!isset($confirmvalue[$confirmkey])) { $confirmvalue[$confirmkey] = $value; } else { if ($confirmvalue[$confirmkey] != $value) { $result->invalidate($tag, '確認欄との入力内容が一致していません'); } } } return $result; } // フィルターフック add_filter('wpcf7_validate', 'wpcf7_validation_confirm', 10, 2); |
俺たちの戦いはまだはじまったばかりだ
よし、内容一致チェックもできたよー。
この辺までの実装で、やっとこさ「それっぽいフォーム」を使えるようになったかなあ。
のレベルにたどり着いた感じです。
他にも目に付くところはあるけれど、今回はここまで!
俺たちの戦いはまだ始まったばかりだ!
コメント
Happy New Year!!!