【WordPress】カスタムフィールドを投稿記事につけて値を取得する

WordPress

WordPressの投稿記事にカスタムフィールドを設置し、値を取得する方法についてのまとめです。(※ACF,SCFを使っててもfunctions.phpで強制的に表示可能)

カスタムフィールドの優良プラグインであるACFがあったんですが、昨今SCFに強制的に変更されるなど、少し今後の行方に不安があるため、とりあえず支障がないならワードプレスにデフォルトでついてるカスタムフィールド機能を使うのもいいのではないかと思っています。

カスタムフィールドとは?

カスタムフィールドは、投稿やページに追加のデータ(メタデータ)を保存する仕組みです。

例えば、WordPressの投稿に「価格」「評価」「発売日」などの情報を追加したいときに使います。
WordPressの標準機能として提供されており、管理画面から直接入力できます。

特徴

  • 投稿ごとに独自のデータを追加・管理できる
  • wp_postmeta テーブルにデータが保存される
  • get_post_meta() でデータの取得が可能

サイトを作っても、価格や発売日などを毎日のように更新するサイトだと、そのページを更新するのも大変になってしまいますが、カスタムフィールドを使えば、ページの中身を細かく見て編集するのではなく、カスタムフィールドの部分だけを見て、そこに値を入力するだけで更新が済みます。

決まった項目の更新作業がある投稿記事につけておくととても役に立つ機能です。

デフォルトのカスタムフィールドのメリット・デメリット

カスタムフィールドにはデフォルトでWordPressについてるものと、ACFやSCFなどのプラグインを使って、コーディングが苦手な人も比較的簡単にカスタムフィールドを実装する方法があります。

WordPressデフォルトのカスタムフィールド vs ACFの比較

項目デフォルトのカスタムフィールドACF(プラグイン)
費用無料無料(Pro版は有料)
安定性コア機能なので安定プラグイン依存(更新やサポート次第)
UIの使いやすさシンプルだが入力が不便直感的なUIで使いやすい
データの種類文字列中心(画像や複雑なデータは手動入力)画像や選択肢など多様なデータを簡単に扱える
カスタマイズ性PHPでのコーディングが必要GUIで設定可能、コード不要
セキュリティ自分でサニタイズ・バリデーションが必要ACF側である程度対策済み
パフォーマンス軽量機能が多いためやや重め

デフォルトのカスタムフィールドを使うにはコーダーの技術力頼りみたいなとこがあり、若干学習コストもかかりますが、一回は実装してみるのも勉強になるのではないかと思います。

カスタムフィールド項目表示の設定

投稿、固定ページを作成する画面で、右上の三点メニューを開き、設定をクリック。高度な設定カスタムフィールド表示のスイッチがあるのでオンにします。右側画面の下のWorksはSCFを使用したときのWorks専用カスタムフィールドです。

これでカスタムフィールドが下の方に出来て、設定することができるようになります。左の図の場合、すでにSCFでカスタムフィールドを作っていたのでそれが表示されており、カスタムフィールドが2ブロックできている状態です。

基本的なデータの使い方

〇データ一覧表示(使用は非推奨)

<?php the_meta(); ?>

現在表示しているページ投稿のIDに紐づいたカスタムフィールド(メタデータ)を取得して表示するためのテンプレートタグ ループ内でのみ使用できる関数、single.phpなどループ内ファイルで使う

データ取得 基本

<?php $meta_values = get_post_meta($post_id, $key, $boolean); ?>

$post_id…カスタムフィールドを取得したい投稿のID
$key…カスタムフィールドのキー
$boolean…配列(false or 記入なし)か個別(true)のデータか(個別のときは条件に合った最初のデータを一つ取ります)

〇個別にデータ取得

例えば「冒頭文」というキーのカスタムフィールドを作って、それを個別で出そうとするとき$intro_text = get_post_meta(get_the_ID(), ‘冒頭文‘, true);

<?php
          // 現在の投稿や固定ページで「冒頭文」というカスタムフィールドの値を取得
          $intro_text = get_post_meta(get_the_ID(), '冒頭文', true);

          // 値が存在する場合のみ出力
          if ($intro_text) {
              echo '<p class="intro-text">' . esc_html($intro_text) . '</p>';
          }
?>

esc_hemlでHTMLエスケープして出力。値が無い時は出力しないように条件分岐

〇複数のデータ取得

このように同じキー名で値が複数あるときは配列でとることができます

<?php 
//複数の値をとる
          $multi = get_post_meta(get_the_ID(), '複数のフィールド', false);
          if ($multi) {
            foreach($multi as $value)
              echo '<p class="intro-text">' . esc_html($value) . '</p>';
          }
?>

〇違うページIDで設定したカスタムフィールドの値を取得

上記までのものは$post_idの引数にget_the_ID()を入れて、現在表示されてるページのIDを出すものですが、サブループやメインループなどの中で使っているとちゃんとそのページのIDがセットされるんですが、例えばフロントページから別の個別ページで設定したカスタムフィールドの値を取得しようとすると、フロントページのIDがセットされてしまうので取得できません。取得したいカスタムフィールドが設定してあるページIDをセットしなければなりません。

例)フロントページで固定プロフィールページに設定したカスタムフィールドを呼び出すとき。

 <?php
            
            // 'profile'というスラッグのページを取得
            $profile_page = get_page_by_path('profile'); // 'profile'はプロフィールページのスラッグです

            // 固定ページのIDを取得
            $profile_page_id = $profile_page->ID;

            // 取得したページのカスタムフィールド「冒頭文」の値を取得
            $intro_text = get_post_meta($profile_page_id, '冒頭文', true);

            // カスタムフィールドが存在する場合のみ表示
            if ($intro_text) {
                echo '<p class="intro-text">' . esc_html($intro_text) . '</p>';
            }
           
?>

ポイントはget_page_by_path(‘profile’)でページを取得し、そのID情報を取得してセットすることです。

〇投稿タイプにカスタムフィールドを一括指定

例えば投稿タイプデフォルトのpostに、サイト更新しやすいように、記入すべき内容をカスタムフィールドであらかじめ記入項目を作っておきたいとき、functions.phpにコードを記述することでそれは可能になります。

functions.phpに追記

function add_empty_custom_fields_on_post_creation($post_id) {
  // 投稿が保存される際、投稿タイプ 'post' の場合にカスタムフィールドを追加
  if (get_post_type($post_id) == 'post') {
      // 'コンテンツ' カスタムフィールドを空で設定
      if (!get_post_meta($post_id, 'コンテンツ', true)) {
          update_post_meta($post_id, 'コンテンツ', '');
      }
      
      // 'タイトル' カスタムフィールドを空で設定
      if (!get_post_meta($post_id, 'タイトル', true)) {
          update_post_meta($post_id, 'タイトル', '');
      }
  }
}
add_action('save_post', 'add_empty_custom_fields_on_post_creation');

save_postは投稿が新規作成、更新されたときにトリガーされるアクションフックです。

メタボックス

メタボックスという機能を使えば、カスタムフィールドのUIを改善できます。これは編集画面内に出るボックスですが、コンテンツ内容として出力されることはなく、カスタムフィールドのように値をコードで取得し出力しなければいけません。

左側のようにちょっとUIが改善してきました。
表示位置はいろいろやってみたけど、下側の一番上に表示が限界かもしれません。あとデフォルトのカスタムフィールドも出てしまっているので、メタボックスでUIを作るなら、デフォルトのカスタムフィールド表示はオフにした方が良いです。

// メタボックスを追加
function my_add_meta_box() {
  add_meta_box(
      'my_meta_box',           // メタボックスの識別子
      'カスタムフィールド',    // メタボックスのタイトル
      'my_custom_meta_box',    // メタボックスの表示内容を決める関数
      'post',                  // 投稿タイプ。ここでは 'post' に追加
      'normal',                // 表示位置(normal, side, advanced)
      'high'                // 優先度
  );
}
add_action( 'add_meta_boxes', 'my_add_meta_box' );

// メタボックスの内容
function my_custom_meta_box( $post ) {
  // 'コンテンツ' カスタムフィールドの値を取得
  $content_value = get_post_meta( $post->ID, 'コンテンツ', true );
  // 'タイトル' カスタムフィールドの値を取得
  $title_value = get_post_meta( $post->ID, 'タイトル', true );

  // 'コンテンツ' フィールドの入力欄
  echo '<label for="content_field">コンテンツ:</label>';
  echo '<textarea id="content_field" name="コンテンツ" rows="4" style="width:100%;">' . esc_textarea( $content_value ) . '</textarea>';
  echo '<br><br>';

  // 'タイトル' フィールドの入力欄
  echo '<label for="title_field">タイトル:</label>';
  echo '<input type="text" id="title_field" name="タイトル" value="' . esc_attr( $title_value ) . '" style="width:100%;">';
}

// メタボックスのデータを保存
function my_save_meta_box_data( $post_id ) {
  // 投稿が自動保存されるときに処理しないようにする
  if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) return;

  // 'コンテンツ' のカスタムフィールドを保存
  if ( isset( $_POST['コンテンツ'] ) ) {
      update_post_meta( $post_id, 'コンテンツ', sanitize_textarea_field( $_POST['コンテンツ'] ) );
  }

  // 'タイトル' のカスタムフィールドを保存
  if ( isset( $_POST['タイトル'] ) ) {
      update_post_meta( $post_id, 'タイトル', sanitize_text_field( $_POST['タイトル'] ) );
  }
}
add_action( 'save_post', 'my_save_meta_box_data' );

こういう風に出力するHtmlをかかなければいけないので結構めんどいです…。

しかしMeta boxを簡単に扱えるプラグインも見つけてしまいました。記事を書きましたので参考になればどうぞ。↓