私がこの記事を書いている時点で、実装できた手順を共有します。
選択肢を動的にする方法はいくつかあったのですが、入力必須とする方法は意外と見つからなかったです。
この記事で実装する機能
- WordPressのメール送信プラグイン「Contact Form 7」で、投稿内にフォームを埋め込む
- フォームには日付の選択を追加する
- 選択肢は「Advanced Custom Fields Pro」の繰り返しフィールドで、投稿ごとに管理する
- 初期状態は空白としておき、能動的な選択を必須にする
- 選択した内容をメールの本文に反映して送信する
全体の流れ
- 入力欄を生成するカスタムショートコードを作成する
- ACFの繰り返しフィールドを、ドロップダウンリストの各項目にする
- 既存のショートコードと同様に、フォームのテンプレートに書き込む
できないこと
ラジオボタン(input type="radio")では「初期状態が空白、かつ選択必須」とすることができません。ドロップダウンリスト(select > option要素)でなければならないことに注意してください。
ラジオボタンは「必ずどれかが選択されている」前提のUIですから、これは当然の仕様と言えます。
また、選択肢と送信内容を違う値にしたり、満員なら disabled にするなどは、Contact Form 7の機能ではできません。フォームを表示させてからJavaScriptで動的に加工する必要があります。
やってはいけない方法
Contact Form 7には、カスタムショートコードを作成する関数がいくつか用意されています。HTMLを直接出力する wpcf7_add_form_tag
が一番簡単で、以下のようにコードを書けば [my_cf7_input]
が使えるようになります…
が、この方法だと入力必須などの、Contact Form 7が用意してくれているオプションを使用できず、今回の要件を満たせません。
function my_add_cf7_event_url(){
ob_start();
global $post;
?>
ここにフォーム入力のHTMLを書く
<?php
return ob_get_clean();
}
wpcf7_add_form_tag('my_cf7_input', 'my_add_cf7_event_url');
望ましい方法
Contact Form 7には、より詳細なカスタムショートコードを作成する関数として wpcf7_form_tag_data_option
が用意されています。
ドロップダウンリストのオプションには、必須を表す *
、初期値空白を表す include_blank
などに加えて、data:任意名
があります。これと wpcf7_form_tag_data_option
を併用すると、選択肢をフォームテンプレートに書くのではなく、PHP処理から渡すことができます。
[select* my_select data:MyOptions include_blank]
wpcf7_form_tag_data_option
の使い方
ショートコードで指定したデータ名 MyOptions
は配列 $options
の値の一つとして渡されています。これを条件に以下の通り、配列 $values
に選択肢を値として渡すと、ドロップダウンリストに反映されます。
空白の選択肢は必要ありません。フォームテンプレート側で include_blank
オプションを付けていれば、空白の選択肢を最初に挿入してくれます。
function my_wpcf7_form_tag_data_option( $values, $options, $args ) {
if( in_array( 'MyOptions', $options ) ) {
$values[] = '選択肢 1';
$values[] = '選択肢 2';
$values[] = '選択肢 3';
return $values;
}
}
add_filter( 'wpcf7_form_tag_data_option', 'my_wpcf7_form_tag_data_option', 10, 3 );
remove_action( 'wpcf7_swv_create_schema', 'wpcf7_swv_add_select_enum_rules', 20, 2 );
フィルターフックを実行したあとで、 wpcf7_swv_create_schema
というアクションフックを解除してください。解除しないと、WordPress 5.9以降でエラーが出るようになりました。
selectのoption値で送信エラーとなる | WordPress.org
最終的なコード
先ほどのコードを拡張して、ACFの繰り返しフィールド my_fields
の日時サブフィールドを選択肢として渡してあげたコードが以下となります。
function my_wpcf7_form_tag_data_option( $values, $options, $args ) {
if( in_array( 'MyOptions', $options ) ) {
while( have_rows( 'my_fields' ) ) :
the_row();
$my_date = get_sub_field( 'my_date' );
$my_time = get_sub_field( 'my_time' );
$values[] = $my_date . ' ' . $my_time;
endwhile;
return $values;
}
}
add_filter( 'wpcf7_form_tag_data_option', 'my_wpcf7_form_tag_data_option', 10, 3 );
remove_action( 'wpcf7_swv_create_schema', 'wpcf7_swv_add_select_enum_rules', 20, 2 );
これで data:MyOptions
が使用可能になったので、以下の通りショートコードを書くと、投稿ごとに異なる選択肢のドロップダウンリストが生成されます。
フォームテンプレート
[select* my_select data:MyOptions include_blank]
メールテンプレート
[my_select]
おわりに
Contact Form 7は、送信ボタンを押したあとは確認画面を表示せず、問題のない内容であればすぐに送信処理を行います。WordPressのフォーム送信プラグインはだいたいこの仕様で、確認画面が出ることが当たり前だった日本でも、利用者側が慣れてきた感があります。
ですが今回のように能動的な選択が必要となる場合、初期値を最初の項目にしていたり、必須チェックをしていないと、思わぬトラブルに繋がります。即送信させるということは、フォームを作る側も慎重になるべきです。
また、公式のフックを利用しているとはいえ、プラグインを加工する以上はアップデート後の仕様変更による不具合リスクがあります。実装したい場合は、納品後のメンテナンスが可能な案件か、まず検討してください。