KH-WEBLOG TOP > WEBメモ > WordPress > ContactForm7のselect選択肢を記事タイトルから自動生成する方法:WordPress

ContactForm7のselect選択肢を記事タイトルから自動生成する方法:WordPress

ContactForm7のselect選択肢をWordPressの記事タイトルから自動生成する方法をご紹介します。

口コミフォーム等に便利で、記事を追加・削除しても、フォーム側を毎回手で直す必要が無くなります。

今回は特定カテゴリ【店舗一覧(スラッグ:shop、ID:2)】の記事のタイトル一覧を出力する前提。

コーディング・WordPress化作業を代行します

ContactForm7側

ContactForm7側は自動生成したい個所に

[shop_select* menu-shop]

のようなコードを入れます。

funcsions.phpに入れるコード

テーマのfunctions.php等に、

/**
 * Contact Form 7: 店舗一覧カテゴリ(shop)の記事タイトルを
 * select項目として自動出力する独自フォームタグ
 */

add_action('wpcf7_init', 'my_cf7_add_shop_select_tag');

function my_cf7_add_shop_select_tag() {
    wpcf7_add_form_tag(
        array('shop_select', 'shop_select*'),
        'my_cf7_shop_select_tag_handler',
        array('name-attr' => true)
    );
}

function my_cf7_shop_select_tag_handler($tag) {
    if (empty($tag->name)) {
        return '';
    }

    $tag  = new WPCF7_FormTag($tag);
    $name = $tag->name;

    $hangover = wpcf7_get_hangover($name);
    $validation_error = wpcf7_get_validation_error($name);

    $class = 'wpcf7-form-control wpcf7-select';
    if ($tag->is_required()) {
        $class .= ' wpcf7-validates-as-required';
    }
    if ($validation_error) {
        $class .= ' wpcf7-not-valid';
    }

    // カテゴリ shop の通常投稿を取得
    $posts = get_posts(array(
        'post_type'      => 'post',
        'post_status'    => 'publish',
        'posts_per_page' => -1,
        'orderby'        => 'title',
        'order'          => 'ASC',
        'category_name'  => 'shop',
    ));

    $options   = array();
    $options[] = '<option value="">クチコミするお店(必須)</option>';

    if (!empty($posts)) {
        foreach ($posts as $shop_post) {
            $title = get_the_title($shop_post->ID);
            $selected = selected($hangover, $title, false);

            $options[] = sprintf(
                '<option value="%1$s"%2$s>%3$s</option>',
                esc_attr($title),
                $selected,
                esc_html($title)
            );
        }
    } else {
        $options[] = '<option value="">店舗がありません</option>';
    }

    $atts = array(
        'name'         => $name,
        'class'        => $class,
        'aria-invalid' => $validation_error ? 'true' : 'false',
    );

    if ($tag->is_required()) {
        $atts['aria-required'] = 'true';
        $atts['required'] = 'required';
    }

    $attr_html = '';
    foreach ($atts as $key => $value) {
        $attr_html .= sprintf(' %s="%s"', $key, esc_attr($value));
    }

    $html  = '<span class="wpcf7-form-control-wrap" data-name="' . esc_attr($name) . '">';
    $html .= '<select' . $attr_html . '>';
    $html .= implode('', $options);
    $html .= '</select>';
    $html .= $validation_error;
    $html .= '</span>';

    return $html;
}

//必須チェック
add_filter('wpcf7_validate_shop_select', 'my_cf7_validate_shop_select', 10, 2);
add_filter('wpcf7_validate_shop_select*', 'my_cf7_validate_shop_select', 10, 2);

function my_cf7_validate_shop_select($result, $tag) {
    $tag = new WPCF7_FormTag($tag);
    $name = $tag->name;

    if (empty($name)) {
        return $result;
    }

    $value = isset($_POST[$name]) ? trim(wp_unslash($_POST[$name])) : '';

    if ($tag->is_required() && $value === '') {
        $result->invalidate($tag, '店舗を選択してください。');
    }

    return $result;
}

でOK

うまく出ない場合の確認ポイント

1. 投稿タイプがpostではない場合

もし「店舗一覧」が通常投稿ではなく、カスタム投稿タイプならpost_typeを変更する必要があります。

たとえばshopというカスタム投稿タイプならこうです。

'post_type' => 'shop',

その場合、

category_name => 'shop'

は不要です。

2. カテゴリ(shop)が通常投稿のカテゴリではない場合

通常投稿のカテゴリなら今回のコードでOKです。
もし独自タクソノミーなら、tax_queryに変える必要があります。

3. 並び順を公開日順にしたい場合

今はタイトル順です。新しい順ならこう変えます。

'orderby' => 'date',
'order'   => 'DESC',

記事ページでは選択肢を非表示にする場合

各記事ページでいちいちその記事を選択させるのは手間ですので、
もし記事ページではその記事が選択されている状態にしつつ選択肢を非表示にしたい場合は
functions.phpのコードを

add_action('wpcf7_init', 'my_cf7_add_shop_select_tag');

function my_cf7_add_shop_select_tag() {
    wpcf7_add_form_tag(
        array('shop_select', 'shop_select*'),
        'my_cf7_shop_select_tag_handler',
        array('name-attr' => true)
    );
}

function my_cf7_shop_select_tag_handler($tag) {
    if (empty($tag->name)) {
        return '';
    }

    $tag  = new WPCF7_FormTag($tag);
    $name = $tag->name;

    $hangover = wpcf7_get_hangover($name);

    global $post;

    $current_post_id = 0;
    $current_title   = '';

    if (get_queried_object_id()) {
        $current_post_id = get_queried_object_id();
    } elseif (isset($post->ID)) {
        $current_post_id = $post->ID;
    }

    if ($current_post_id) {
        $current_title = get_the_title($current_post_id);
    }

    $is_shop_single = false;

    if (
        $current_post_id &&
        is_singular('post') &&
        has_category('shop', $current_post_id)
    ) {
        $is_shop_single = true;
    }

    $validation_error = wpcf7_get_validation_error($name);

    $class = 'wpcf7-form-control wpcf7-select';
    if ($tag->is_required()) {
        $class .= ' wpcf7-validates-as-required';
    }
    if ($validation_error) {
        $class .= ' wpcf7-not-valid';
    }

    // 店舗記事ページでは hidden
    if ($is_shop_single) {
        $value = '';

        if ($hangover !== '') {
            $value = $hangover;
        } elseif ($current_title !== '') {
            $value = $current_title;
        }

        $html  = '<span class="wpcf7-form-control-wrap" data-name="' . esc_attr($name) . '">';
        $html .= '<input type="hidden" name="' . esc_attr($name) . '" value="' . esc_attr($value) . '">';
        $html .= $validation_error;
        $html .= '</span>';

        return $html;
    }

    // それ以外では select
    $posts = get_posts(array(
        'post_type'      => 'post',
        'post_status'    => 'publish',
        'posts_per_page' => -1,
        'orderby'        => 'title',
        'order'          => 'ASC',
        'category_name'  => 'shop',
    ));

    $options   = array();
    $options[] = '<option value="">クチコミするお店(必須)</option>';

    if (!empty($posts)) {
        foreach ($posts as $shop_post) {
            $title = get_the_title($shop_post->ID);
            $selected = selected($hangover, $title, false);

            $options[] = sprintf(
                '<option value="%1$s"%2$s>%3$s</option>',
                esc_attr($title),
                $selected,
                esc_html($title)
            );
        }
    }

    $html  = '<span class="wpcf7-form-control-wrap" data-name="' . esc_attr($name) . '">';
    $html .= '<select name="' . esc_attr($name) . '" class="' . esc_attr($class) . '" aria-invalid="' . ($validation_error ? 'true' : 'false') . '">';
    $html .= implode('', $options);
    $html .= '</select>';
    $html .= $validation_error;
    $html .= '</span>';

    return $html;
}

add_filter('wpcf7_validate_shop_select', 'my_cf7_validate_shop_select', 10, 2);
add_filter('wpcf7_validate_shop_select*', 'my_cf7_validate_shop_select', 10, 2);

function my_cf7_validate_shop_select($result, $tag) {
    $tag = new WPCF7_FormTag($tag);
    $name = $tag->name;

    if (empty($name)) {
        return $result;
    }

    $value = isset($_POST[$name]) ? trim(wp_unslash($_POST[$name])) : '';

    if ($tag->is_required() && $value === '') {
        $result->invalidate($tag, '店舗を選択してください。');
    }

    return $result;
}

のように変更すればOKです。

コーディング・WordPress化作業を代行します

WordPressのおすすめ参考書

楽天Kobo電子書籍ストア
¥3,278 (2026/03/21 01:45時点 | 楽天市場調べ)

TAGS

.htaccess ActionScript All in one seo pack Contact Form 7 CSS CSS3 EC-CUBE Flash HTML HTML5 JavaScript jQuery LightBox PHP RSS SEO WordPress アイキャッチ画像 アクセス解析 カスタムフィールド カテゴリー カラーミーショップ カート コメント ショートコード テンプレートタグ ドロップダウンメニュー パーマリンク フォーム フルスクリーン ブログカード プラグイン ページテンプレート ページナビ ページ分割 マウスイベント リダイレクト リンク リンクカード レンタルサーバー ロールオーバー 携帯サイト 条件分岐 正規表現 関連記事