WebTecNote

[WordPress] Contact Form 7 のフォームをReactやVueで作り変えるためのTips

WordPressで一番使われてるだろうお問い合わせフォームプラグインContact Form7の、
フォーム部分をVue.jsで作り変える必要が出たのでその時に調べた仕様とかのメモ。

コンタクトフォーム記事IDの取得

Contact Form 7はカスタム投稿タイプ wpcf7_contact_form で記事が作成される。
データベースが変わらないのであればJS内で決め打ちしていいが、環境でデータベースが異なるならIDをWordpress側から受け取るようにする。

get_postsの利用

タイトルやスラッグを元にIDを取得する。

$form = get_posts(array(
  'post_type' => 'wpcf7_contact_form',
  'post_status' => 'publish',
  'title' => 'お問い合わせ' // title
  // ,'name' => 'contact-form' // slug
));
// var_dump($form[0]->ID);

get_optionの利用

別に設定画面を用意してそこにフォーム記事IDを登録するという手もある。

var_dump((int) get_option('wpcf7-form-id'));

HTML

input[type=hidden]で以下3つ必要。

<!-- [contact-form-7 id="123" title="お問い合わせ"] -->
<input type="hidden" name="_wpcf7" value="123">
<input type="hidden" name="_wpcf7_unit_tag" value="wpcf7-f123-p1000-o1">
<input type="hidden" name="_wpcf7_locale" value="ja">

_wpcf7 の値は上記で取得したコンタクトフォームの記事IDで、ショートコードにIDで記載されるものと同じ。
_wpcf7_locale は言語。
_wpcf7_unit_tag の値はショートコードがHTMLタグに変換される時に生成されるもので、以下の構文で作成する。
wpcf7-f[フォームのID]-p[フォームを埋め込んでる記事ID]-o[記事内のフォーム番号]
※埋め込む記事IDがないなら3番目のpから始まる部分は省略
※記事内のフォーム番号は1から始まる連番。

ex:Vue.js

<input type="hidden" name="_wpcf7" v-model="formId">
<input type="hidden" name="_wpcf7_unit_tag" v-model="unitTag">
computed: {
  unitTag() {
    return `wpcf7-f${this.formId}-p${this.postId}-o1`;
  }
}

送信

送信先は
/wp-json/contact-form-7/v1/contact-forms/フォーム記ID/feedback
である。

const formData = new FormData( document.getElementById('form') );

axios.post(`/wp-json/contact-form-7/v1/contact-forms/${formId}/feedback`, formData)
  .then(res => {
    console.log(res);
  })
  .catch(error => {
    console.log(error);
  });   

Response

statusは validation_failed, acceptance_missing, spam, aborted, mail_sent, mail_failed, custom で、messageは管理画面で設定したもの。
エラーの場合はinvalidFieldsでエラーになっているフォームの情報が帰ってくる。

// Success
{
  into: "#", // unit_tag
  message: "ご利用ありがとうございます。送信が完了しました。",
  status: "mail_sent"
}

// Error
{
 into: "#", // unit_tag
 invalidFields: [
   {
     idref: "your-email", // フォームのname
     into: "span.wpcf7-form-control-wrap.your-email" //className
     message: "この項目は入力必須です。"
   }
 ],
 message: "1つ以上のフィールドにエラーがあります。 確認してからもう一度お試しください。",
 status: "validation_failed"
}

ex:Vue.js

<form v-on:submit.prevent="onSubmit" ref="form">

<!-- ブラウザのバリデーション使わない場合 -->
<form v-on:submit.prevent="onSubmit" ref="form" novalidate>
methods: {
  onSubmit() {
     if ( typeof window.FormData !== 'function' ) {
        return;
     }

     const formData = new FormData( this.$refs.form );

     axios.post(`/wp-json/contact-form-7/v1/contact-forms/${this.formId}/feedback`, formData)
      .then(res => {
        console.log(res);
      })
      .catch(error => {
        console.log(error);
      }); 
  }
}

追加の設定

config.phpに追加するもの

// トークンチェックをオフにする
define ('WPCF7_VERIFY_NONCE', false);

// ContactForm7のJSを読み込まない
define ('WPCF7_LOAD_JS', false);

// ContactForm7のCSSを読み込まない
define ('WPCF7_LOAD_CSS', false);

以下はContactForm7のスパム判定を変更するフィルター。
テーマのfunctions.phpに追加する。

add_filter( 'wpcf7_recaptcha_verify_response',
  function( $is_human, $response_body ) {
    $score = isset( $response_body['score'] ) ? $response_body['score'] : 0;
    $threshold = 0.1;
    $is_human = $threshold < $score;
    return $is_human;
  },
  10, 2
);
モバイルバージョンを終了