Amazonで商品を見る セール会場へ

WordPress│フォームから記事投稿する│Contact Form 7

Contact Form 7の入力から、ログインした投稿権限のあるユーザー自身の下書きを作成する例です。

対象はタイトルとプレーンテキストの本文で、画像・カテゴリー・タグは保存後にWordPressの編集画面から設定します。

旧稿の匿名投稿と画像コピーのコードは撤回しました。

旧画像処理は同名ファイルを上書きし得るうえ、投稿権限・実際の画像形式・保存失敗を十分に確認していませんでした。

目次

著者

WEB制作をしているデジタルノマド
WordPressのカスタマイズが好きで、色々と自作しています。

WordPressのカスタマイズに困ったらご相談ください!

変更前に旧コードを停止する

検証環境でデータベースとスニペットをバックアップし、旧稿のcf7_create_post、wpcf7_insert_image_post、cf7_create_post_with_thumbnailと、そのフック登録を停止します。

旧画像用のadd_attachment_from_form・cf7_add_attachmentも、この用途で追加したものか確認して取り除きます。

新旧のフックを同時に有効にすると、1回の送信で別々の記事を作成する可能性があります。

Contact Form 7のフォームを設定する

専用フォームの「フォーム」欄に次の内容を設定します。

<label>タイトル(200文字以内)
[text* post-title maxlength:200]
</label>
<label>本文(20000文字以内・HTMLは使用しない)
[textarea* post-content maxlength:20000]
</label>
[submit "下書きを保存"]

「その他の設定」欄には次の1行を入れます。

subscribers_only: true

この設定でフォームをログインユーザー向けにし、PHP側ではさらにedit_posts権限を確認して購読者からの保存を拒否します。

「メッセージ」欄の送信成功メッセージは「下書きを保存しました。」へ変更します。

この例は対象フォームのメール送信を省略するため、メール送信成功を保存成功の根拠にはしません。

フォームを載せるページを共有キャッシュの対象から外し、ログイン後に読み込み直してください。

下書き保存用のPHPを追加する

PHPのmbstring拡張を利用できる環境で、子テーマのfunctions.phpかCode SnippetsのPHPスニペットへ追加し、waza_draft_form_id()の97を専用フォームの実際のIDへ変更します。

既存のPHPファイル内やCode Snippetsへ貼る場合、先頭の<?phpは追加しません。

// 対象のCF7フォームIDへ変更する。
function waza_draft_form_id() { return 97; }

// ログイン中のフォームにREST用nonceを出力させる。
add_filter('wpcf7_verify_nonce', function ($active, $form) {
    return (int) $form->id() === waza_draft_form_id() ? true : $active;
}, 10, 2);

add_action('wpcf7_before_send_mail', function ($form, &$abort, $submission) {
    if ((int) $form->id() !== waza_draft_form_id() || $abort) return;
    $nonce = $_POST['_wpnonce'] ?? '';
    if (!current_user_can('edit_posts') || !is_string($nonce)
        || !wp_verify_nonce(wp_unslash($nonce), 'wp_rest')) {
        $abort = true;
        $submission->set_response('ログイン状態と投稿権限を確認して、フォームを読み込み直してください。');
        return;
    }
    $title = $submission->get_posted_data('post-title');
    $body = $submission->get_posted_data('post-content');
    if (!is_string($title) || !is_string($body)) {
        $abort = true;
        $submission->set_response('入力形式を確認してください。');
        return;
    }
    $title = sanitize_text_field($title);
    $body = sanitize_textarea_field($body);
    if ($title === '' || $body === '' || mb_strlen($title) > 200 || mb_strlen($body) > 20000) {
        $abort = true;
        $submission->set_response('タイトルは200文字、本文は20000文字以内で入力してください。');
        return;
    }
    $content = '<!-- wp:paragraph --><p>' . nl2br(esc_html($body)) . '</p><!-- /wp:paragraph -->';
    $id = wp_insert_post(wp_slash([
        'post_type' => 'post', 'post_status' => 'draft',
        'post_title' => $title, 'post_content' => $content,
        'post_author' => get_current_user_id(),
    ]), true);
    if (is_wp_error($id) || !$id) {
        $abort = true;
        $submission->set_response('下書きを保存できませんでした。管理者へ確認してください。');
    }
}, 10, 3);

// このフォームではメール送信を行わず、下書き保存を結果とする。
add_filter('wpcf7_skip_mail', function ($skip, $form) {
    return (int) $form->id() === waza_draft_form_id() ? true : $skip;
}, 10, 2);

投稿者ID・公開状態は送信値から受け取らず、現在のユーザーとdraftに固定しています。

権限やnonceが不正な場合、配列入力・空の入力・上限超過がある場合、保存が失敗した場合は処理を中止します。

送信結果から確認先を選ぶ

送信後の状態次に確認する場所・操作
「下書きを保存しました。」投稿一覧で本人の下書きが1件増えたか確認し、タイトル・本文を照合する
ログイン状態と投稿権限の案内投稿権限と対象フォームIDを確認。ログイン後にフォームページを読み込み直す
入力形式・文字数の案内タイトル200文字・本文20000文字以内の文字列を入力する。PHPは配列入力を受け付けない
下書きを保存できない案内再送する前に投稿一覧を確認し、管理者が保存処理とログを調べる
応答が分からない・もう一度送信したい投稿一覧で同じ内容の下書きを確認する。再送は別の下書きを作る

確認は「フォームの応答」「投稿一覧」「保存内容」の順に行います。この例は、送信後に作られた投稿IDをフォームへ返す処理を持ちません。投稿一覧で送信時刻・投稿者・タイトルを照合して対象を特定します。

まず検証環境で短いタイトルと2行の本文を送信し、本人の下書きだけが増えるかを確認します。次に匿名・購読者・空欄で保存されないか確認し、通常のお問い合わせフォームには下書き保存の処理やメール省略が適用されないことも比較してください。

共有キャッシュから古いフォームが表示された疑いがある場合は、対象ページの除外設定を確認して読み込み直します。エラーが出るたびにキャッシュ設定全体を変更するのではなく、投稿権限・フォームID・保存済み下書きの有無を先に切り分けます。

保存後の確認と戻し方

投稿権限のあるユーザーでタイトルと本文を送信し、管理画面の「投稿」から下書きが1件作られたことを確認します。

投稿者・タイトル・本文を照合し、必要なカテゴリー・タグ・アイキャッチ画像を編集画面で設定してから公開します。

この例には送信ごとに1回だけ保存する保証がなく、再送すると別の下書きが作られます。

結果が不明なときは再送する前に投稿一覧を確認してください。

フォームからの画像取り込みと、同時送信を含む重複防止が必要な運用は、この例の対象外です。

戻す場合は今回のPHPスニペットを停止し、フォーム設定とメッセージを変更前へ戻します。

スニペットの停止だけでは作成済みの下書きは戻らないため、管理画面で対象を確認して整理します。

実HTTPで確認した送信結果

送信条件HTTP・フォーム応答投稿一覧の確認
投稿権限のあるユーザー・有効nonceHTTP 200、mail_sent本人の下書きが1件増える
無効nonceHTTP 403、rest_cookie_invalid_nonce下書きは増えない
匿名送信HTTP 200、error下書きは増えない

HTTP 200だけで保存成功と判断せず、CF7の応答と投稿一覧を照合します。

この専用フォームはメールを省略するため、mail_sentは受信メールの到達を意味しません。

日本語と改行、バックスラッシュを含む本文を保存でき、入力したscriptタグが実行用HTMLとして残らないことを確認しました。

フォームIDは検証用へ変更しており、本番に検証データは送信していません。

確認した範囲

2026年10月2日、WordPress 7.1.2とContact Form 7 6.1.7の隔離環境で、実プラグインの送信処理から下書き保存を確認しました。

管理者・投稿者の保存、匿名・購読者・不正nonce・配列入力・空欄の拒否を検証しています。

2026年10月3日には、通常のWordPressログインで取得したCookieと、フォームが発行したnonceを使い、CF7のREST送信から投稿者本人の下書きを1件保存できることも確認しました。

ブラウザーでのフォーム操作、スマホ表示、キャッシュとの組み合わせは未検証です。

フォームの設置はContact Form 7の公式手順、保存処理はWordPressのwp_insert_post()仕様も確認してください。

  • URLをコピーしました!

実装を任せたい方へ

WordPressのカスタマイズ代行

ブロックの追加、テーマの改修、管理画面の調整など、記事で紹介している内容の実装を承ります。1時間 ¥8,000〜(税込)。

WAZAの有料記事のサブスクリプションも開始しました。

サービス

Service

WordPressサイトのカスタマイズのサービスに関心がありましたら、ぜひ詳細をご覧ください。

目次