Contact Form 7、WordPressでサイトを構築するときによく利用する、有名なフォーム作成プラグインです!このプラグインでセレクトボックスを挿入する際、以下のようなショートコードを埋め込みます。
[select select-name "value1" "value2" "value3"]
この、「value1, value2, value3」となっているのが、セレクトボックスの中の選択肢なのですが、例えば、年月日の「月」のセレクトボックスを設けようとすると、このようなショートコードを用意する必要が出てきます。
[select select-month "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" "11" "12"]
…いや、動的に出したくない??「年」の時、きつくない??
他にも、投稿のカテゴリーを選択肢として出すとか、特定の投稿タイプのタイトルを選択肢として出すとか、そんな要望がきっとあるはず。
ぐぐってみると…出てくるやり方は、wpcf7_add_form_tag() を使ってオリジナルのフォームタグ(ショートコード)を作ってみようというもの。
…天下の Contact Form 7 が、選択肢いじくれるフィルターフックを用意してないとか、あるのかと。。。
ということで、きっと、すでにどこかで既出だとは思いますが、フィルターフックを見つけましたよというお話です!
※Contact Form 7 の v.5.1.4 で確認しています。
フィルターフックの見つけ方
いつもの grep を使って、セレクトボックスを生成しているコードを特定していきます。
[kusanagi@minkapi contact-form-7]$ grep -irn '<option' * modules/select.php:101: $html .= sprintf( '<option %1$s>%2$s</option>', modules/number.php:169: <option value="number" selected="selected"><?php echo esc_html( __( 'Spinbox', 'contact-form-7' ) ); ?></option> modules/number.php:170: <option value="range"><?php echo esc_html( __( 'Slider', 'contact-form-7' ) ); ?></option>
ファイル名からして生成している感あふれる「modules/select.php」を覗いてみます。
foreach ( $values as $key => $value ) { if ( $hangover ) { $selected = in_array( $value, (array) $hangover, true ); } else { $selected = in_array( $value, (array) $default_choice, true ); } $item_atts = array( 'value' => $value, 'selected' => $selected ? 'selected' : '', ); $item_atts = wpcf7_format_atts( $item_atts ); $label = isset( $labels[$key] ) ? $labels[$key] : $value; $html .= sprintf( '<option %1$s>%2$s</option>', $item_atts, esc_html( $label ) ); }
option タグを生成しているのは101~102行目で、$values で foreach して生成していることから、この $values に選択肢が格納されているはず。そこで、$values がどう作られたのか遡って確認してみる。
if ( $data = (array) $tag->get_data_option() ) { $tag->values = array_merge( $tag->values, array_values( $data ) ); $tag->labels = array_merge( $tag->labels, array_values( $data ) ); } $values = $tag->values; $labels = $tag->labels;
61行目の $tag->get_data_option() で何かしら取れれば、それを array_merge() して選択肢として利用しているみたい。 $tag->get_data_option() を grep で探索。
[kusanagi@minkapi contact-form-7]$ grep -irn 'function get_data_option(' * includes/form-tag.php:319: public function get_data_option( $args = '' ) {
「includes/form-tag.php」の該当行を覗いてみる。
public function get_data_option( $args = '' ) { $options = (array) $this->get_option( 'data' ); return apply_filters( 'wpcf7_form_tag_data_option', null, $options, $args ); }
やっぱり!フィルターフック発見しましたー!!ぱちぱち
引数確認すると、ショートコードの data 属性で判別することができそうです。
フィルターフックを利用して選択肢を動的に出力してみた
Contact Form 7 側のショートコードは以下のように入力します。
[select month data:AutoMonth]
ショートコード内では、選択肢は特に入力しません。このショートコードが年月日の「月」を出力したいんだと判別できるように、data 属性として「AutoMonth」を指定しています。
あとは、独自プラグインでもfunctions.php でも、以下のようにフックしてあげればOK!
add_filter( 'wpcf7_form_tag_data_option', 'custom_select_values', 10, 3 ); function custom_select_values( $values, $options, $args ) { if ( in_array( 'AutoMonth', $options ) ) { $values = range( 1, 12 ); } return $values; }
これで、選択肢には自動で1~12の整数が表示されます。
if 文を増やせば、複数のセレクトボックスの中身をいじれますし、今回は range() で整数をつっこんでるだけですが、カテゴリー名だって投稿タイトルだって、配列形式で渡してあげれば動的に出力されます。
選択肢を動的に出したいだけの場合は、このフィルターフックを使う方が wpcf7_add_form_tag() より圧倒的におすすめです!
ちょこっと追記
記事を書き終えた後に、公式サイトを見ていたらこんな記事を見つけました。
あれ?これ、今回取り上げたフック使ってるんじゃないか…?
[kusanagi@minkapi contact-form-7]$ grep -irn 'wpcf7_form_tag_data_option' * includes/form-tag.php:322: return apply_filters( 'wpcf7_form_tag_data_option', null, $options, $args ); modules/listo.php:7:add_filter( 'wpcf7_form_tag_data_option', 'wpcf7_listo', 10, 3 );
やっぱり!!!!!!