Top Blog(category) contact form

single.php

コンタクトフォーム

目次

エラー事例

  • form.php⇒confirm.phpに遷移しない(URLもhome/formから変化しない)
  • 固定ページのスラッグ実装は正常
  • バリデーションチェックが全て動作していない(一部入力されていない場合でも遷移してしまう)
  • confirm.phpを直接開くとヘッダーのみ表示されているが、他は白画面になっている

formの要素

構成要素

  • 名前
  • 電話番号
  • メールアドレス
  • タイトル
  • 問い合わせ内容
  • プライバシーポリシーへの同意
  • 送信ボタン

構成ページ

  • 入力
  • 確認
  • 完了
  • エラー

機能

  • バリデーション
  • hoverの色
  • placeholder
  • プライバシーポリシーは別タブ

🔁 formフロー図(簡易)

  1. ユーザーが <button type="submit">送信</button> をクリック
  2. <form method="post"> により、同じページへ POST リクエストが送られる
  3. PHPの冒頭で $_SERVER['REQUEST_METHOD'] === 'POST' を検知
  4. 送信処理(メール送信・セッション初期化など)を実行
  5. wp_redirect(home_url('/thanks/')) により「thanksページ」へリダイレクト
  6. exit; によりそれ以降の処理は実行されない

<form method="post"> と設定されたフォームで、<button type="submit">送信</button> をクリックすると、POSTリクエストが実行されます。そして、PHP側で POST 処理が行われ、条件により wp_redirect()exit; が呼ばれると、別のURLへリダイレクトされます。

method=”post”:POSTリクエストで送信される

action=””:空欄の場合、現在のURL(このテンプレートページ)に送信

type=”submit”:フォームを送信するボタン

wp_nonce_field():CSRF対策のセキュリティトークンを埋め込む

<form method="post" action="">
  <?php wp_nonce_field('contact_confirm', 'confirm_form_nonce'); ?>
  <button type="submit">送信する</button>
</form>

✅ まとめ

  • <form><button type="submit"> → POSTリクエストが発生
  • PHP側の if ($_SERVER['REQUEST_METHOD'] === 'POST') で処理を分岐
  • wp_redirect()exit; によりリダイレクトが行われ、HTMLは出力されない

この仕組みをベースに「確認画面 → 完了画面」の流れを作っている形です。必要に応じて POSTデータの検証やログ出力なども追加できます。

✅【1】action 属性の基本と具体的な使用パターン

🔹action とは:

  • <form> タグの属性で、「送信先URL(どのページにPOST/GETするか)」を指定します。
  • 指定がない(空)場合は、現在表示しているページ(自分自身)に送信される

🔸使用例:

◆パターンA:自身のページでバリデーションをしてから別ページへリダイレクト(今回推奨)

<form method="post" action="<?php echo esc_url( get_permalink() ); ?>">

→ こうすると、まず自分のテンプレート内でバリデーションを行い、問題なければ wp_redirect() で確認画面へ進める
WordPressテーマや一般的なWebフォームでもよく使われる構成です。

◆パターンB:直接別ページ(例:/confirm)へ送信

<form method="post" action="<?php echo esc_url( home_url( '/confirm' ) ); ?>">

→ こちらは confirm.php 側にバリデーション処理をすべて実装している場合に限って有効です。
ただし、セキュリティやエラー表示の観点からやや設計が複雑になるため、初心者や管理しやすさを重視するなら パターンA(自分にPOST)を推奨します。

formのinputで設定する属性値

<input>にはいくつか属性値を設定します。それぞれを関連付けてユーザーが操作しやすくしたり、開発者が読みやすいコードになります。それぞれの意味は以下を参考にしてください。

type=””

typeでよく使用するのはtext、checkbox、radioです。

label =”for”とinput id=””

name=””とvalue=””

nameはキー、valueは値として$_POSTメソッドの連想配列として保持されます。formでの入力データはあくまで一時的なもので特に理由が無ければデータベースに記録しません。PHPの連想配列として格納されるのはvalue=””に入力されたデータで$_SESSIONからPHPコードで呼び出す際には連想配列$_POSTのname属性として参照します。$_POST[‘name’]

またiputには閉じタグが無いので、ユーザーが入力した値、文字列はvalueに設定されます。入力された内容を$_SESSIONに保存するためにinput=”<?php echo esc_attr($_POST[‘name’]); ?>”のようにエスケープ処理しておきます。

required=””

HTMLのvalue属性は、入力欄の初期値を設定したり、テキスト入力欄に入力された値を読み取る際に使用されます。入力必須の項目を定義する際は、required属性を使用します。value属性自体は必須ではありませんが、特にテキスト入力欄では初期値や入力された値を保持するために役立ちます。

  <section id="contact-form">
    <form action="">
      <table>
        <tr>
          <td><label for="">お名前</label></td>
          <td><input type="text" name="name" id="name" placeholder="お名前"></td>
        </tr>
        <tr>
          <td><label for="">メールアドレス</label></td>
          <td><input type="text" name="name" id="name" placeholder="メールアドレス"></td>
        </tr>
        <tr>
          <td><label for="">電話番号</label></td>
          <td><input type="text" name="name" id="name" placeholder="電話番号"></td>
        </tr>
        <tr>
          <td><label for="">タイトル
          </label></td>
          <td><input type="text" name="name" id="name" placeholder="タイトル"></td>
        </tr>
        <tr>
          <td><label for="">内容</label></td>
          <td><textarea type="text" name="name" id="name" placeholder="内容を入力してください"></textarea></td>
        </tr>
      </table>
      <div class="send-wrapper">
        <p><input type="checkbox" name="privacy" id="privacy">
        <a href="<?php echo esc_url( get_permalink( get_page_by_path( 'privacy-policy' ) ) ); ?>" target="_blank" rel="noopener noreferrer">プライバシーポリシー</a>
        に同意する</p>
        <button type="send">送信</button>
      </div>
    </form>
  </section>

confirm.phpで$_SESSIONに格納された入力値を取得する

$_SESSIONで引き継いだ値をメールとして送信する

<form>の中の<button type=”submit”>を押すとPOSTリクエストを実行します。以下のページではwp_mail();の後で送信完了のthanksページにリダイレクト(遷移)します。

<?php
/*
Template Name: contact確認ページ
*/
get_header();
session_start(); // セッション開始

// セッションが存在しない or 不正アクセス
if (empty($_SESSION['form'])) {
    wp_redirect(home_url('/contact/'));
    exit;
}

$form = $_SESSION['form'];

// フォーム送信処理(確認→完了)
if ($_SERVER['REQUEST_METHOD'] === 'POST' 
&& isset($_POST['contact_confirm_nonce']) 
&& wp_verify_nonce($_POST['contact_confirm_nonce'], 'contact_confirm')) {

    // メール送信処理
    $to = get_option('admin_email');
    $subject = '【お問い合わせ】' . $form['subject'];
    $body = <<<EOT
以下の内容でお問い合わせがありました。

お名前: {$form['name']}
メール: {$form['email']}
電話番号: {$form['phone']}
タイトル: {$form['subject']}
メッセージ:
{$form['message']}
EOT;

    $headers = ['Content-Type: text/plain; charset=UTF-8'];

    wp_mail($to, $subject, $body, $headers);

    // セッションを削除して完了ページへリダイレクト
    unset($_SESSION['form']);
    wp_redirect(home_url('/contact-thanks/'));
    exit;
}
?>

<?php get_footer(); ?>

入力された値を確認する

nonceでトークンを発行


<main>
  <h1>入力内容の確認</h1>

  <section id="contact-confirm">
    <form method="post">
      <?php wp_nonce_field('contact_confirm', 'contact_confirm_nonce'); ?>
      <table>
        <tr><td>お名前</td><td><?php echo esc_html($form['name']); ?></td></tr>
        <tr><td>メールアドレス</td><td><?php echo esc_html($form['email']); ?></td></tr>
        <tr><td>電話番号</td><td><?php echo esc_html($form['phone']); ?></td></tr>
        <tr><td>タイトル</td><td><?php echo esc_html($form['subject']); ?></td></tr>
        <tr><td>内容</td><td><?php echo nl2br(esc_html($form['message'])); ?></td></tr>
      </table>

      <div class="button-group">
        <button type="submit">送信する</button>
        <a href="<?php echo esc_url(home_url('/contact/')); ?>">戻って修正</a>
      </div>
    </form>
  </section>
</main>

form.phpのPOSTリクエスト

if ($_SERVER['REQUEST_METHOD'] === 'POST' 
    && isset($_POST['contact_form_nonce']) 
    && wp_verify_nonce($_POST['contact_form_nonce'], 'contact_form')) {
    // フォームのバリデーション処理
}
・
・
・
<?php wp_nonce_field('contact_form', 'contact_form_nonce'); ?>

🔹$_SERVER['REQUEST_METHOD'] === 'POST'

  • 意味:現在のHTTPリクエストが POST送信かどうか を判定します(他にはGETなどがある)
  • POSTとは:フォームからデータをサーバーに送る時の一般的な方法。HTTPリクエストの1つ(他にGETもあります)
  • つまり:「送信ボタンが押された」ことを判定する条件です。

🔹 isset($_POST['contact_form_nonce'])

  • 意味:$_POST 配列に 'contact_form_nonce' というキーが存在しているかチェック。
  • なぜ必要?:フォームから意図通りに nonce(ノンス)が送られているかを確認するため。
  • issetを使う理由:存在しないキーを参照すると「Noticeエラー」になるため、安全に扱うため。

nonce

生のPHPとWordPressの違い

項目生のPHPWordPress
ルーティングform.phpなどのURLに直アクセス固定ページ + テンプレート
メール送信mail()wp_mail()
CSRF対策自作トークンwp_nonce_field()
フォーム検証$_POSTで直接処理sanitize_text_field()などのWordPress関数推奨
セッションsession_start()で自由に使用可手動で有効化必要(functions.phpに記述)

参考になるコンタクトフォームのテンプレート