LESSON / WP LOAD

ACFを使わずカスタムフィールドを実装する

WordPress標準のメタボックスと投稿メタを使い、制作実績へ担当範囲を入力・保存・表示します。

目安 120分 コース進捗 0 / 17

GOAL

このレッスンでできるようになること

  • メタボックスと投稿メタの関係を説明できる
  • nonce・権限・入力値を確認して保存できる
  • 保存した値を安全にテンプレートへ表示できる

制作実績へ「担当範囲」のような決まった情報を追加する場合は、投稿メタへ保存できます。このレッスンではACFを使わず、WordPress標準APIで入力欄から表示までを実装します。

管理画面に入力欄を出すだけでは安全に保存できません。送信元、権限、自動保存、入力値を確認してからデータベースへ保存します。

メタボックスを登録する

カスタムフィールドは入力欄を追加するだけでなく、安全を確認して保存する処理まで必要です。

独自入力欄の値をnonce、権限、無害化の確認後に保存して表示する流れ
独自入力欄の値をnonce、権限、無害化の確認後に保存して表示する流れ
function wpload_add_works_meta_box() {
 add_meta_box(
  'wpload_works_details',
  '制作情報',
  'wpload_render_works_meta_box',
  'works',
  'normal',
  'default'
 );
}
add_action( 'add_meta_boxes', 'wpload_add_works_meta_box' );

第4引数のworksは表示対象の投稿タイプです。通常投稿や固定ページには表示されません。

入力欄とnonceを表示する

function wpload_render_works_meta_box( $post ) {
 $scope = get_post_meta( $post->ID, '_wpload_work_scope', true );
 wp_nonce_field( 'wpload_save_works_meta', 'wpload_works_nonce' );
 ?>
 <p>
  <label for="wpload-work-scope">担当範囲</label>
 </p>
 <p>
  <input
   id="wpload-work-scope"
   name="wpload_work_scope"
   type="text"
   value="<?php echo esc_attr( $scope ); ?>"
   class="widefat"
  >
 </p>
 <p class="description">例:デザイン、コーディング、WordPress構築</p>
 <?php
}

メタキーをアンダースコアから始めると、WordPress標準のカスタムフィールド欄には通常表示されません。nonceは、意図した管理画面から送られた処理か確認するために使います。

次の画像は、「入力欄とnonceを表示する」で扱うコードや構成をブラウザで表示した結果です。

「入力欄とnonceを表示する」で扱うコードや構成の表示結果
「入力欄とnonceを表示する」で扱うコードや構成をブラウザで表示した結果

安全を確認して保存する

function wpload_save_works_meta( $post_id ) {
 if ( ! isset( $_POST['wpload_works_nonce'] ) ) {
  return;
 }

 $nonce = sanitize_text_field( wp_unslash( $_POST['wpload_works_nonce'] ) );
 if ( ! wp_verify_nonce( $nonce, 'wpload_save_works_meta' ) ) {
  return;
 }

 if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
  return;
 }

 if ( 'works' !== get_post_type( $post_id ) ) {
  return;
 }

 if ( ! current_user_can( 'edit_post', $post_id ) ) {
  return;
 }

 if ( ! isset( $_POST['wpload_work_scope'] ) ) {
  return;
 }

 $scope = sanitize_text_field( wp_unslash( $_POST['wpload_work_scope'] ) );

 if ( '' === $scope ) {
  delete_post_meta( $post_id, '_wpload_work_scope' );
  return;
 }

 update_post_meta( $post_id, '_wpload_work_scope', $scope );
}
add_action( 'save_post_works', 'wpload_save_works_meta' );

nonceの確認だけでは権限確認になりません。current_user_can()も使い、編集権限のある利用者だけが保存できるようにします。

次の図では、「安全を確認して保存する」の仕組みや関係を確認できます。

「安全を確認して保存する」の仕組みや関係を示す図
「安全を確認して保存する」の仕組みと関係

詳細ページへ表示する

保存した制作情報は、未入力時を考慮しながら詳細ページへ分かりやすく表示します。

制作実績の詳細ページへ担当範囲などのカスタムフィールドを表示した例
制作実績の詳細ページへ担当範囲などのカスタムフィールドを表示した例
<?php
$scope = get_post_meta( get_the_ID(), '_wpload_work_scope', true );
?>

<?php if ( '' !== $scope ) : ?>
 <dl class="work-details">
  <div>
   <dt>担当範囲</dt>
   <dd><?php echo esc_html( $scope ); ?></dd>
  </div>
 </dl>
<?php endif; ?>

保存時に無害化していても、出力する場所に合わせてエスケープします。文章として表示するためesc_html()を使います。URLならesc_url()、HTML属性ならesc_attr()を使います。

入力と更新を確認する

  1. 担当範囲を入力して更新する
  2. 管理画面を再読み込みし、値が残っているか確認する
  3. 詳細ページへ値が表示されるか確認する
  4. HTMLに見える文字を入力し、そのまま文字として表示されるか確認する
  5. 値を空にして更新し、表示欄ごと消えるか確認する
  6. 別の権限のユーザーで入力欄と保存可否を確認する

項目が増えたら、入力形式、必須か任意か、誰が編集できるか、一覧やREST APIにも必要かを項目ごとに設計します。

次の図では、「入力と更新を確認する」の仕組みや関係を確認できます。

「入力と更新を確認する」の仕組みや関係を示す図
「入力と更新を確認する」の仕組みと関係

CHECK POINT

完了条件