MW WP Formでフォームのバリデーションとエラーをカスタマイズする【WordPress/PHP】

WordPress

高機能なフォームを手軽に作成できる『MW WP Form』は、WordPressでお馴染みのプラグインです。
今回、フォームに必須のバリデーション(入力チェック)およびエラー表示をカスタマイズしました。
希望通りに実装できたのでメモ。ちょっとコードが怪しいですが、、。

MW WP Formとは

直感的にフォームを作成できるWordPressのプラグインです。

多くのフォーム作成プラグインは、確認画面に遷移せず送信が完了するタイプですが、『MW WP Form』は確認画面を作成できるのがポイントです。バリデーションの細かい条件も管理画面から直感的に設定できます。

今回は管理画面からバリデーションを設定するのではなく、全てfunctions.phpにコードを記述して実装します。なるべくコピペで済むようにメモしておきます。

バリデーションを実装したフォーム(デモ)

こちらがバリデーションを実装したデモです!
尚、このブログで使用しているのは無料のWordPressテーマ『Cocoon』です。
エラーメッセージの表示など、テーマの構造によってはコードの変更が必要です。

動作デモ

カスタマイズした内容

カスタマイズした内容は次の通りです。

  • エラーメッセージの文言と表示位置をカスタマイズ
  • エラーの件数を画面上部に表示
  • 複数の項目で、回答が1つもない場合エラーを表示させる
  • ある項目を選択した場合、テキストフィールドを必須項目にする
  • 生年月日など複数のエラーをまとめる

カスタマイズの基本(PHP)

バリデーションとエラーメッセージは、子テーマのfunctions.phpで設定します。
次の関数の中に、バリデーションルールを追記していきます。

functions.php

function form_validation_rule($Validation, $data, $Data)
{
  // バリデーションの内容を記述

  return $Validation;
}

add_filter('mwform_validation_mw-wp-form-XXXX', 'form_validation_rule', 10, 3);

コードの中のmwform_validation_mw-wp-form-XXXXの「XXXX」は、フォームを作成した時に発行される「フォーム識別子」を設定します。

エラーメッセージの文言と表示位置をカスタマイズ

デフォルトだと、エラーメッセージは項目の下に表示されます。
必須項目にした場合のエラーメッセージは、デフォルトだと「必須項目です。」や「未入力です。」になります。

デフォルト

エラーメッセージの位置を項目の上に移動し、メッセージ内容も変更したいと思います。
ついでにCSSで見た目も調整します。

カスタマイズ後

コピペするコード

MW WP Form管理画面

フォームのショートコードにshow_error=”false”を指定して、デフォルトのエラーが表示されないようにします。実際にエラーを表示させたい箇所に[mwform_error keys=”<KEY>”]を記載します。

// MW WP Form管理画面に記載
<div class="display-error">[mwform_error keys="性別"]</div> //エラーが表示される場所
<p class="mb10">性別(必須)</p>
[mwform_radio name="性別" children="男性,女性" show_error="false" vertically="true"]

functions.php

表示するエラーメッセージを指定します。

function form_validation_rule($Validation, $data, $Data)
{
  // 性別(ラジオボタン)が選択されていない場合
  $Validation->set_rule('性別', 'required', array('message' => '性別を選択してください'));
}

add_filter('mwform_validation_mw-wp-form-XXXX', 'form_validation_rule', 10, 3);

上記のように表示したいエラーメッセージを設定します。構文は次の通りです。

$Validation->set_rule(‘KEY’, ‘バリデーションルール’, array(‘message’ => ‘エラーメッセージ));

バリデーションルールは大抵「noEmpty」を指定するとエラーを判定できますが、ラジオボタンの場合はスルーされるようです。
「required」にするとエラーを判定できました。バリデーションルールは色々あるので、本家サイトを確認した方が良いかもしれません。

MW WP Form
ショートコードによるフォーム作成MW WP Form はシンプルなショートコードを記述して入力フィールドを追加していきます。フォーム作成画面には自由にHTMLを入力することができるので自由にフォームをデザインする...

あとは見た目をCSSで調整します。

CSS

/* エラー */
.mw_wp_form .error {
    background: #ffeaea;
    padding: 0.3em 0.5em;
    margin-bottom: 10px;
    display: block;
    flex: 0 1 100%;
}

エラーの件数を画面上部に表示

バリデーションチェックに引っかかった際、各項目にエラーを表示させるのはもちろん、画面の上部にどんなエラーがあるか表示させたいのですが、実装方法がわかりませんでした、、。
最終的にはJSで実現しました。

エラー項目を表示させるのは難しかったので、画面の上部にエラーが何件あるか表示し、ページ内リンクで移動するようにしました。

画面上部にエラーが何件あるか表示させる

コピペするコード

JavaScript

function formErrorAppear() {
    // エラーの数を取得
    const errorElm = document.querySelectorAll(".error");

    if (errorElm.length > 0) {
        // 表示するエラーの要素を作成
        errorElm[0].id = "errorTarget";
        const createErrorElm = document.createElement('div');
        const errorElemText = document.createTextNode(`入力エラーが${errorElm.length}件あります`);

        const createtargetElm = document.createElement('a');
        const targetElemText = document.createTextNode(`エラーに移動する▼`);

        createtargetElm.href = "#errorTarget";
        createtargetElm.appendChild(targetElemText);

        createErrorElm.appendChild(errorElemText);
        createErrorElm.appendChild(createtargetElm);

        createErrorElm.classList.add("error-notice");

        const parentElm = document.querySelector(".article-header"); // 要素を追加する親要素
        const titleElm = document.querySelector(".entry-title"); // この要素の前に追加
        parentElm.insertBefore(createErrorElm, titleElm);

    }
}
// 実行
formErrorAppear();
});

CSS

/* エラー */
.mw_wp_form .error {
    background: #ffeaea;
    padding: 0.3em 0.5em;
    margin-bottom: 10px;
    display: block;
    flex: 0 1 100%;
}
.error-notice {
    color: #B70000;
    background: #ffeaea;
    padding: 14px;
    text-align: center;
}
.error-notice a {
    display: block;
    font-size: 0.8em;
}

ページが読み込まれた時、エラー項目が何件あるか取得し、要素を作成してページに挿入します。
一番最初のエラーにページ内リンクのアンカー(id)を追加します。
テーマがCocoonだったらコピペで動きそうですが、それ以外のテーマは要素を挿入する設定を変更する必要があります。

具体的には次の部分です。

const parentElm = document.querySelector(".article-header"); // 要素を追加する親要素
const titleElm = document.querySelector(".entry-title"); // この要素の前に追加

insertBefore() メソッドで要素を挿入します。要素を追加する親要素と挿入直前の要素をセレクタで指定します。
Cocoonの場合、タイトル直前の位置にエラー要素が挿入されます。

Cocoonは、固定ページごとにJSやCSSを設定できます。それができないテーマの場合、関数の実行を制限した方が良いかもしれません。

例えば以下のように、URLで関数を実行するページを制限します。

  // フォームのページだけ実行
  if (currrentURL.indexOf(/mw-wp-form-error/) > 0 ) {
      formErrorAppear();
  }

複数の項目で、回答が1つもない場合エラーを表示させる

アンケートフォームなどで、最低1つの質問には答えて欲しい!という時に使えそうです。
Q1サービス、Q2頻度、Q3満足の内、1つも回答がない場合、エラーを表示します。

コピペするコード

MW WP Form管理画面

<div class="display-error">[mwform_hidden name="アンケート_エラー" show_error="false"][mwform_error keys="アンケート_エラー"]</div>
<p class="q">Q1. あなたが、このサービスを知ったきっかけをお聞かせください(複数選択可)</p>
[mwform_checkbox name="サービス" children="テレビ,新聞,雑誌,検索エンジン,SNS・ブログ,家族・友人・知人,その他" separator="," vertically="true"]
[mwform_textarea name="その他" cols="50" rows="5" placeholder="その他を選択した場合、入力してください" ]

<p class="q">Q2. あなたが、このサービスを利用する頻度をお聞かせください</p>
[mwform_radio name="頻度" children="ほぼ毎日,1週間に一回,1ヶ月に数回,2〜3ヶ月に数回,それ以下" vertically="true"]

<p class="q">Q3. あなたは、このサービスにどれくらい満足していますか</p>
[mwform_radio name="満足" children="満足,やや満足,普通,やや不満,不満" vertically="true"]

複数項目のエラーはhiddenタグのエラーとして表示させます。
エラーを表示させたい箇所にhiddenタグを追加します。

functions.php

function form_validation_rule($Validation, $data, $Data)
{
  // サービスメニューのチェック
  if (
    isset($data['サービス']) ||
    isset($data['頻度']) ||
    isset($data['満足']) 
  ) {

    if (
      empty($data['サービス']['data']) &&
      empty($data['頻度']) &&
      empty($data['満足']) 
    ) {
      $Validation->set_rule('アンケート_エラー', 'noEmpty', array('message' => '最低1つの質問にお答えください'));
    }
  }
  return $Validation;
}

add_filter('mwform_validation_mw-wp-form-XXXX', 'form_validation_rule', 10, 3);

issetで変数が存在していれば、それぞれの項目の値が取得できているか確認します。
どの項目にも値がない場合は、hiddenタグのエラーを表示します。

CSS

/* 必須 */
.require {
    font-size: .7em;
    background: #ff0000;
    padding: 0.3em 0.5em;
    color: #fff;
    margin-left: 5px;
}

ある項目を選択した場合、テキストフィールドを必須項目にする

ある項目を選択したときは、ここを入力して欲しい!ってことがあると思います。
そんな時に使えそうなサンプルです。

チェックボックスの「その他」を選択した時は、テキストフィールドの入力が必須になります。

コピペするコード

MW WP Form管理画面

<p class="q">Q1. あなたが、このサービスを知ったきっかけをお聞かせください(複数選択可)</p>
[mwform_checkbox name="サービス" children="テレビ,新聞,雑誌,検索エンジン,SNS・ブログ,家族・友人・知人,その他" separator="," vertically="true"]
<div class="display-error">[mwform_error keys="その他"]</div>
[mwform_textarea name="その他" cols="50" rows="5" placeholder="その他を選択した場合、入力してください" show_error="false"]

fnctions.php

function form_validation_rule($Validation, $data, $Data)
{
  // その他を選択した場合
  if (
    in_array('その他', $data['サービス']['data'])
  ) {
    $Validation->set_rule('その他', 'noEmpty', array('message' => 'その他を選択した場合、入力をお願いします'));
  }

  return $Validation;
}

add_filter('mwform_validation_mw-wp-form-XXXX', 'form_validation_rule', 10, 3);

生年月日など複数のエラーをまとめる

生年月日の年と月、日、全てを選択しないとエラーになるように設定します。
カスタマイズしないと年と月、日それぞれのエラーが表されます。

これだと少しわかりにくいので、3つのエラーをまとめて表示させます。
エラーの文言もわかりやすいものに変更します。

コピペするコード

MW WP Form管理画面

<div class="display-error">[mwform_error keys="年,月,日"]</div>
<p class="mb10">生年月日(必須)</p>
<div class="barth_area">[mwform_select name="年" class="yarea" children=":--,2017(平成29),2016(平成28),2015(平成27),2014(平成26),2013(平成25),2012(平成24),2011(平成23),2010(平成22),2009(平成21),2008(平成20),2007(平成19),2006(平成18),2005(平成17),2004(平成16),2003(平成15),2002(平成14),2001(平成13),2000(平成12),1999(平成11),1998(平成10),1997(平成9),1996(平成8),1995(平成7),1994(平成6),1993(平成5),1992(平成4),1991(平成3),1990(平成2),1989(平成元年),1988(昭和63),1987(昭和62),1986(昭和61),1985(昭和60),1984(昭和59),1983(昭和58),1982(昭和57),1981(昭和56),1980(昭和55),1979(昭和54),1978(昭和53),1977(昭和52),1976(昭和51),1975(昭和50),1974(昭和49),1973(昭和48),1972(昭和47),1971(昭和46),1970(昭和45),1969(昭和44),1968(昭和43),1967(昭和42),1966(昭和41),1965(昭和40),1964(昭和39),1963(昭和38),1962(昭和37),1961(昭和36),1960(昭和35),1959(昭和34),1958(昭和33),1957(昭和32),1956(昭和31),1955(昭和30),1954(昭和29),1953(昭和28),1952(昭和27),1951(昭和26),1950(昭和25),1949(昭和24),1948(昭和23),1947(昭和22),1946(昭和21),1945(昭和20),1944(昭和19),1943(昭和18),1942(昭和17),1941(昭和16),1940(昭和15),1939(昭和14),1938(昭和13),1937(昭和12),1936(昭和11),1935(昭和10),1934(昭和9),1933(昭和8),1932(昭和7),1931(昭和6),1930(昭和5),1929(昭和4),1928(昭和3),1927(昭和2),1926(昭和元年),1925(大正14),1924(大正13),1923(大正12),1922(大正11),1921(大正10),1920(大正9),1919(大正8),1918(大正7),1917(大正6),1916(大正5),1915(大正4),1914(大正3),1913(大正2),1912(大正元年),1911(明治44),1910(明治43),1909(明治42),1908(明治41)" post_raw="true" show_error="false"] 年 [mwform_select select name="月" class="marea" children=":--,1,2,3,4,5,6,7,8,9,10,11,12" post_raw="true" show_error="false"] 月 [mwform_select select name="日" class="darea" children=":--,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" post_raw="true" show_error="false"] 日
</div>

エラーはカンマで区切ることでまとめて記載できます。

例)[mwform_error keys=”年,月,日”]

また、セレクトボックスのデフォルトをエラー(空)として判定したい場合、先頭にコロンを追加します。

例)children=”:–,1,2,3,4,5,6,7,8,9,10,11,12″

fnctions.php

function form_validation_rule($Validation, $data, $Data)
{
  // 年月日をまとめる
  $validation_message = '生年月日を入力してください';

  if (empty($data['年'])) {
    $Validation->set_rule('年', 'noEmpty', array('message' => $validation_message));
  } elseif(empty($data['月'])) {
    $Validation->set_rule('月', 'noEmpty', array('message' => $validation_message));
  } elseif(empty($data['日'])) {
    $Validation->set_rule('日', 'noEmpty', array('message' => $validation_message));
  }

  return $Validation;
}

add_filter('mwform_validation_mw-wp-form-1906', 'form_validation_rule', 10, 3);

年、月、日の値が空だったらエラーを表示します。

まとめ

最終的になんとか希望通りの動きを実装することができました!
バリデーションは管理画面で設定した方が直感的で分かりやすいです。ただ、カスタマイズする時はコードでの記述が必要になります。

最初は管理画面からバリデーションを設定していましたが、この方法でカスタマイズした方が管理が楽だと思いました。