リクルートサイトのエントリーフォームで、「希望職種」や「雇用形態」のセレクトボックスの選択肢を、サイト側の登録内容と常に一致させておきたい——求人が増減するたびにフォームを手直しするのは手間ですし、更新漏れも起こりがちです。
結論から言うと、Contact Form 7のセレクトボックスの選択肢を、タクソノミーのタームやカスタム投稿のタイトルから自動生成することで、この問題を解決できます。この記事では、functions.phpに追記する2パターンのコードを解説します。

たとえば上のようなエントリーフォームで、雇用形態や希望職種をカスタムタクソノミーで登録しておき、そのタームをセレクトボックスの選択肢として自動で出力すれば、フォームとサイトの内容が常に一致します。求人の追加・削除に、フォームが自動で追従してくれるのが利点です。
1つ目は、カスタムタクソノミーのターム一覧を選択肢にするパターンです。functions.phpに次のコードを追記します。
// Contact Form 7 セレクトボックスの選択肢をタクソノミーのターム一覧から自動生成
add_filter('do_shortcode_tag', function ($output, $tag, $attr) {
if ('contact-form-7' === $tag || 'contact-form' === $tag) {
$id = 10; // コンタクトフォームの ID
$name = 'select-recruit'; // セレクトボックスの名前
$tax = 'recruit_type'; // タクソノミーのスラッグ
if ($id == $attr['id']) {
$terms = get_terms($tax, array('hide_empty' => false));
if (!empty($terms) && !is_wp_error($terms)) {
$options = '<option value="">選択してください</option>';
foreach ($terms as $term) {
$options .= '<option value="' . esc_attr($term->name) . '">' . esc_html($term->name) . '</option>';
}
$output = preg_replace('/(<select .*?name="' . $name . '".*?>)(.*?)(<\/select>)/i', '${1}' . $options . '${3}', $output);
}
}
}
return $output;
}, 10, 3);
このコードは、do_shortcode_tagフィルターでフォームの出力HTMLを受け取り、指定したnameのセレクトボックスの中身を、タームから生成した<option>で置き換えています。$id(フォームID)・$name(セレクトボックス名)・$tax(タクソノミーのスラッグ)の3つを、自分の環境に合わせて書き換えれば動作します。
Contact Form 7側には、置き換え先となる空のセレクトボックス(例:[select select-recruit])を用意しておきます。あとはタームを追加・編集するだけで、選択肢が自動で更新されます。
なお、get_terms()は、WordPressのバージョンによってはget_terms(array('taxonomy' => $tax, 'hide_empty' => false))という新しい書き方が推奨されます。上記のコードでタームが取得できない場合は、この形も試してみてください。
2つ目は、カスタム投稿のタイトル一覧を選択肢にするパターンです。求人名(=カスタム投稿のタイトル)をそのまま選択肢にしたい場合に便利です。
// Contact Form 7 セレクトボックスの選択肢をカスタム投稿のタイトルから自動生成
function job_selectlist($tag, $unused)
{
// セレクトボックスの名前が 'select-job' かどうか
if ($tag['name'] != 'select-job') {
return $tag;
}
// get_posts() でセレクトボックスの中身を作成する
$args = array(
'numberposts' => -1,
'post_type' => 'job', // カスタム投稿タイプを指定
'orderby' => 'ID', // 並び順 = セレクトボックス内の表示順
'order' => 'ASC'
);
$job_posts = get_posts($args);
// 投稿がなければそのまま戻す
if (!$job_posts) {
return $tag;
}
// セレクトボックスに foreach で入れる
foreach ($job_posts as $job_post) {
$tag['raw_values'][] = $job_post->post_title;
$tag['values'][] = $job_post->post_title;
$tag['labels'][] = $job_post->post_title;
}
return $tag;
}
add_filter('wpcf7_form_tag', 'job_selectlist', 10, 2);
こちらはwpcf7_form_tagフィルターを使い、フォームタグそのものに選択肢を追加する方式です。セレクトボックス名がselect-jobのときだけ、get_posts()で取得したカスタム投稿(job)のタイトルを、選択肢として1つずつ差し込んでいます。
どちらの方法も「サイトの登録内容とフォームの選択肢を自動で一致させる」という目的は同じですが、選択肢の元にするデータが異なります。
扱いたいデータがタクソノミーか投稿かで、使うフィルターを選べば迷いません。どちらも一度設定すれば、あとは管理画面での登録・編集だけで選択肢が自動更新されるので、運用の手間がぐっと減ります。
2つのコードで使っているフィルターが違う点も押さえておくと理解が深まります。do_shortcode_tagは出力されたHTMLを後から書き換える方式、wpcf7_form_tagはフォームタグが作られる段階で選択肢を組み込む方式です。前者はHTMLを正規表現で置換するぶん対象の指定がやや繊細で、後者はContact Form 7の仕組みに沿って値を渡すため素直に扱えます。どちらでも実現できますが、迷ったらカスタム投稿の例で使ったwpcf7_form_tag方式のほうが扱いやすいでしょう。
do_shortcode_tagで出力HTMLを置き換えるwpcf7_form_tagでフォームタグに追加する選択肢の自動生成は、更新漏れによる「フォームとサイトの内容の食い違い」を防ぐ、運用面で効果の大きい実装です。求人サイトはもちろん、店舗一覧やサービス一覧など、項目が増減するフォーム全般で活用できます。