Practical example 02

フロントエンドフォームで
新規投稿を作成する

atshift Fieldsで作成したフィールドグループを、ログインユーザー向けの入力フォームとしてWebサイト側へ表示し、指定した投稿タイプへ新規投稿を作成する実装例です。

01

この実装でできること

  • 設定画面で作成したフィールドグループをフロントエンドへ表示する。
  • 投稿タイプを指定し、ログインユーザーが新しい下書きを作成する。
  • タブ、アコーディオン、条件分岐、繰り返しフィールドを同じフォーム内で利用する。
利用するAPI

CFS()->form() が入力欄、nonce、フォームセッション、保存処理をまとめて提供します。

02

フィールドグループを用意する

  1. 「設定 → atshift Fields」でフィールドグループを作成します。
  2. 使用するフィールドを追加し、必須項目や行数上限を設定します。
  3. 編集画面のURLにある post=123 の数値から、フィールドグループIDを確認します。

以下のコードにある 123 は、実際のフィールドグループIDへ置き換えてください。

03

非ログイン送信を拒否する

テーマの functions.php またはサイト専用プラグインへ追加します。新規投稿は投稿タイプの create_posts 権限で判定します。

functions.php

PHP / 権限
<?php
add_filter(
  'cfs_form_can_save',
  function ( $can_save, $post_id, $post_data ) {
    if ( ! is_user_logged_in() ) {
      return false;
    }

    $post_type = sanitize_key( $post_data['post_type'] ?? 'post' );
    $object    = get_post_type_object( $post_type );

    return $object
      && current_user_can( $object->cap->create_posts );
  },
  10,
  5
);
このフィルターは、フォームのHTMLを直接書き換えて送信された場合にも保存を拒否します。nonceはCSRF対策であり、ログインや投稿権限の代わりにはなりません。
04

フォーム用CSS・JavaScriptを読み込む

フォームを設置する固定ページのスラッグを front-form とした例です。wp_head() より前に登録されるよう、wp_enqueue_scripts から読み込みます。

functions.php

PHP / Assets
<?php
add_action( 'wp_enqueue_scripts', function () {
  if ( is_page( 'front-form' ) && is_user_logged_in() ) {
    CFS()->form->load_assets();
  }
} );
05

ページテンプレートへフォームを表示する

フォームを設置した固定ページから、member_entry 投稿タイプの下書きを新規作成します。

固定ページはフォームの表示場所です

このテンプレートを設定した固定ページ自体へ値を保存するわけではありません。post_typepost を指定すれば通常の投稿へ、カスタム投稿タイプ名を指定すればその投稿タイプへ保存されます。

page-front-form.php

PHP / Template
<?php
/* Template Name: CFS Front-end Form */

if ( ! is_user_logged_in() ) {
  auth_redirect();
}

$post_type = 'member_entry'; // 保存先のカスタム投稿タイプを指定

get_header();
?>

<main class="front-form">
  <h1>新しく登録</h1>

  <?php
  echo CFS()->form( array(
    'post_id'              => false, // falseなら新規作成
    'field_groups'         => array( 123 ), // 使用するフィールドグループID
    'post_type'            => $post_type, // 保存先のカスタム投稿タイプ
    'post_status'          => 'draft', // 新規投稿は下書きで保存
    'post_title'           => 'タイトル',
    'submit_label'         => '保存する',
    'confirmation_url'     => home_url( '/front-form/?saved=1' ),
  ) );
  ?>
</main>

<?php get_footer(); ?>
既存投稿を編集したい場合

既存投稿の更新は、既存投稿編集編post_id を使う方法を紹介しています。

06

非ログインで公開する場合の防御

公開フォームとして運用する場合は、ログイン限定とは別の設計が必要です。

  • 投稿先を固定:投稿タイプ、投稿ステータス、フィールドグループIDをサーバー側で固定する。
  • 大量送信対策:IP・セッション単位の回数制限、CAPTCHA、WAFを利用する。
  • サイズ制限:文字数、配列数、繰り返し行数、リクエスト全体の容量を制限する。
  • 入力検証:メール、URL、数値などを型別に検証し、HTMLは許可タグを限定する。
  • ID検証:関連投稿、ユーザー、ターム、添付ファイルIDが選択可能な対象か確認する。
  • ファイル制限:MIMEタイプ、拡張子、容量、アップロード権限を制限する。
  • 出力時エスケープ:保存時の処理とは別に、表示場所に応じて esc_html()esc_url()wp_kses_post() などを使う。
基本方針

公開する理由がなければ、非ログインユーザーはサーバー側で拒否するのが最も確実です。

07

運用前に確認する

  • 非ログイン状態でフォームURLを開くとログイン画面へ移動する。
  • 許可されたユーザーだけが新規投稿を作成できる。
  • タブ、条件分岐、繰り返しフィールドが表示・保存できる。
  • 送信後の投稿タイプと投稿ステータスが想定どおりになっている。
  • 保存した値を表示するとき、用途に合ったエスケープを行っている。