WordPress

カスタムフィールドをプラグインなしで追加する方法

WordPressのカスタムフィールドはプラグインのAdvanced Custom Fieldsを利用すると簡単に追加し活用することができますが、当方はプラグインを利用しないようにしています。プラグインは入れれば入れるほど重くなりますし、動作干渉によるバグも起こりやすくなりますので、できるだけ利用を控えたいというのが理由です。

当初は、項目数が多ければプラグインを使おうと思ってましたが、慣れてきまして、今となっては、プラグインを使って、プラグイン側での不具合が起こった場合や、プラグインのサポートが終わった場合のことを考えると怖くて、プラグインを使う気は今のところありません。

ここでは、プラグインなしでカスタムフィールドを追加するコードと、その解説を致します。

カスタムフィールドとは

カスタムフィールドとは、WordPressの管理画面に入力項目を設置し、そこに入力された値を活用してサイトに反映できる機能で、この機能自体はWordPressにデフォルトで備わっています。

入力項目を管理画面に表示するには、プラグインを利用するか、functions.phpへの追記が必要になります。

カスタムフィールドの追加方法(プラグインなし)

ここでは、店舗A、店舗B、店舗Cでそれぞれ住所を入力する項目を設置する例としてコードをお示しします。

PHP

<?php
//カスタムフィールドのメタボックス
function add_custom_fields(){
   add_meta_box(
      'custom_field_01', //セクションのID
      '店舗住所', //セクションのタイトル
      'insert_shop_fields', //フォーム部分を指定する関数
      'page', //投稿タイプの場合は「post」、カスタム投稿タイプの場合は「スラッグ名」、固定ページの場合は「page」
      'normal', //セクションの表示場所
      'high'  //優先度
    );
  }
add_action('admin_menu', 'add_custom_fields');
 
//カスタムフィールドの入力エリア
function insert_shop_fields() {
  global $post;
  //nounceフィールドの追加
  wp_nonce_field('custom_field_save_meta_box_data', 'custom_field_meta_box_nonce');
echo '
<table class="custom-fields">
  <tr class="border-top border-bottom">
     <th scope="row">
       <label for="shop_a">店舗A</label>
     </th>
     <td> 
       <input type="text" id="shop_a" name="shop_a" value="'.get_post_meta($post->ID, 'shop_a', true).'" />
     </td>
   </tr>
   <tr class="border-bottom">
      <th scope="row">
        <label for="shop_b">店舗B</label>
      </th>
      <td> 
        <input type="text" id="shop_b" name="shop_b" value="'.get_post_meta($post->ID, 'shop_b', true).'" />
      </td>
   </tr>
   <tr class="border-bottom">
   <th scope="row">
     <label for="shop_c">店舗C</label>
   </th>
   <td> 
     <input type="text" id="shop_c" name="shop_c" value="'.get_post_meta($post->ID, 'shop_c', true).'" />
   </td>
</tr>
</table>
';
}
 
//カスタムフィールドの値を保存
function save_custom_fields( $post->ID ) {
  //nonceがセットされているか確認
  if (!isset($_POST['custom_field_meta_box_nonce'])) {
   return;
 }
 //nounceが正しいか検証
   if (!wp_verify_nonce($_POST['custom_field_meta_box_nonce'], 'custom_field_save_meta_box_data')) {
    return;
}
$key = 'shop_a';
if(!empty($_POST[$key])) { //入力済みの場合
  update_post_meta($post->ID, '$key', $_POST[$key] ); //値を保存
} else { //未入力の場合
  delete_post_meta($post->ID, '$key'); //値を削除
}
$key = 'shop_b';
if(!empty($_POST[$key])) { //入力済みの場合
  update_post_meta($post->ID, '$key', $_POST[$key] ); //値を保存
} else { //未入力の場合
  delete_post_meta($post->ID, '$key'); //値を削除
}
$key = 'shop_c';
if(!empty($_POST[$key])) { //入力済みの場合
  update_post_meta($post->ID, '$key', $_POST[$key] ); //値を保存
} else { //未入力の場合
  delete_post_meta($post->ID, '$key'); //値を削除
}
}
add_action('save_post', 'save_custom_fields');
?>

なお、後段のカスタムフィールドの値を保存するところの記述ですが、項目が多くなると行数が長くなってしまうので、私は実務では次のように記述しています。

$key = 'shop_a'; if(!empty($_POST[$key])){update_post_meta($post->ID,'$key',$_POST[$key]);}else{delete_post_meta($post->ID,'$key');}
$key = 'shop_b'; if(!empty($_POST[$key])){update_post_meta($post->ID,'$key',$_POST[$key]);}else{delete_post_meta($post->ID,'$key');}
$key = 'shop_c'; if(!empty($_POST[$key])){update_post_meta($post->ID,'$key',$_POST[$key]);}else{delete_post_meta($post->ID,'$key');}

こうすると、$key= 'xxx'のところを変えるだけというのがやりやすくなって、そんなにプラグインなしが苦じゃなくなってくると思います。

設置結果

次のように、WordPressの投稿編集画面または固定ページ編集画面に入力項目が設置されました。ただし、この見た目はCSSで調整していて、デフォルトの見た目とは異なります。

コードの解説

add meta box

まず、カスタムフィールドを追加する関数add_meta_boxを用います。引数の詳細はこちらのページなど参照されると載っています。
ここでは固定ページに追加する例として'page'と書いている部分は、通常の投稿タイプであれば'post'、カスタム投稿タイプの場合はそのスラッグ名を'スラッグ名'と書きます。
セクションの表示場所は、'normal'では編集画面の下部に表示されますが、'side'とすると右側のパネルに項目が表示されます。
優先度は'high'にしないと、他のもの(例えばプラグイン「All in One SEO」の項目)の下の方に表示される場合があります。
insert_shop_fieldsと書いてある部分は、その後の関数名と揃える必要があります。

wp_nonce_field

wp_nonce_fieldの関数を使ってフォームを設置します。
フォームのHTMLを書いて、そのフォームに入力がされていれば保存、入力がなければ保存されていた値を削除する、というコードになっています。
uppdate_post_metaはカスタムフィールドの値を上書きする関数で、引数は投稿(ページ)のID、フォームのname属性の値、更新する値の順です。delete_post_metaはカスタムフィールドの値を削除する関数です。

特定のページに対してのみカスタムフィールドを追加する場合

上記は、固定ページ、投稿ページ、カスタム投稿ページの種別で一括追加されますが、特定のページにしか関係ないものの場合、そのページにだけ足したいという場合もあるでしょう。その場合の方法についてご説明します。

スラッグで指定

まずスラッグで指定する場合、以下の4~8行目と、20~25行目が先ほど異なる部分です。この例では、スラッグ名がtopの場合で示しています。

<?php
//カスタムフィールドのメタボックス
function add_custom_fields(){
  $post_id = '';
  if(isset($_GET&#91;'post'&#93;) || isset($_POST&#91;'post_ID'&#93;)) {
    $post_id = $_GET&#91;'post'&#93; ? $_GET&#91;'post'&#93; : $_POST&#91;'post_ID'&#93; ;
  }
  if ($post_id == get_page_id('top')){
   add_meta_box(
      'custom_field_01', //セクションのID
      '店舗住所', //セクションのタイトル
      'insert_shop_fields', //フォーム部分を指定する関数
      'page', //投稿タイプの場合は「post」、カスタム投稿タイプの場合は「スラッグ名」、固定ページの場合は「page」
      'normal', //セクションの表示場所
      'high'  //優先度
    );
  }
add_action('admin_menu', 'add_custom_fields');
//ページIDを取得する関数の定義
function get_page_id($post_name)
{
  global $wpdb;
  $id = $wpdb->get_var("SELECT ID FROM $wpdb->posts WHERE post_name = '".$post_name."'");
  return esc_html($id);
}
//カスタムフィールドの入力エリア
function insert_shop_fields() {
  global $post;
  //nounceフィールドの追加
  wp_nonce_field('custom_field_save_meta_box_data', 'custom_field_meta_box_nonce');
echo '
省略
';
}
//カスタムフィールドの値を保存
function save_custom_fields( $post_id ){
  //nonceがセットされているか確認
  if (!isset($_POST['custom_field_meta_box_nonce'])) {
   return;
  }
 //nounceが正しいか検証
   if (!wp_verify_nonce($_POST['custom_field_meta_box_nonce'], 'custom_field_save_meta_box_data')) {
    return;
   }
  $key = 'shop_a'; if(!empty($_POST[$key])){update_post_meta($post_id,'$key',$_POST[$key]);}else{delete_post_meta($post_id,'$key');}
  $key = 'shop_b'; if(!empty($_POST[$key])){update_post_meta($post_id,'$key',$_POST[$key]);}else{delete_post_meta($post_id,'$key');}
  $key = 'shop_c'; if(!empty($_POST[$key])){update_post_meta($post_id,'$key',$_POST[$key]);}else{delete_post_meta($post_id,'$key');}
}
add_action('save_post', 'save_custom_fields');
?>

ページIDで指定

次の記述は、ページのIDで指定する場合です。4行目がページ種別で指定する場合と異なる部分です。ページのIDは、管理画面の編集画面URLの末尾で確認できます。この例では、IDが1の場合で示しています。

<?php
//カスタムフィールドのメタボックス
function add_custom_fields(){
  if ( ( $post = get_post() ) && ( $post->ID === 1 ) ) {
   add_meta_box(
      'custom_field_01', //セクションのID
      '店舗住所', //セクションのタイトル
      'insert_shop_fields', //フォーム部分を指定する関数
      'page', //投稿タイプの場合は「post」、カスタム投稿タイプの場合は「スラッグ名」、固定ページの場合は「page」
      'normal', //セクションの表示場所
      'high'  //優先度
    );
  }
add_action('admin_menu', 'add_custom_fields');
//カスタムフィールドの入力エリア
function insert_shop_fields() {
  global $post;
  //nounceフィールドの追加
  wp_nonce_field('custom_field_save_meta_box_data', 'custom_field_meta_box_nonce');
echo '
省略
';
}
//カスタムフィールドの値を保存
function save_custom_fields( $post->ID ){
  //nonceがセットされているか確認
  if (!isset($_POST['custom_field_meta_box_nonce'])) {
   return;
  }
 //nounceが正しいか検証
   if (!wp_verify_nonce($_POST['custom_field_meta_box_nonce'], 'custom_field_save_meta_box_data')) {
    return;
   }
  $key = 'shop_a'; if(!empty($_POST[$key])){update_post_meta($post_id,'$key',$_POST[$key]);}else{delete_post_meta($post_id,'$key');}
  $key = 'shop_b'; if(!empty($_POST[$key])){update_post_meta($post_id,'$key',$_POST[$key]);}else{delete_post_meta($post_id,'$key');}
  $key = 'shop_c'; if(!empty($_POST[$key])){update_post_meta($post_id,'$key',$_POST[$key]);}else{delete_post_meta($post_id,'$key');}
}
add_action('save_post', 'save_custom_fields');
?>

まとめ

カスタムフィールドをプラグインなしで設置する方法をご紹介しました。
設置した項目の値を活用する方法はこちらをご参照ください。

著者のイメージ画像

株式会社BringFlower
稲田 高洋(Takahiro Inada)

2003年から大手総合電機メーカーでUXデザインプロセスの研究、実践。UXデザイン専門家の育成プログラム開発。SEOにおいても重要なW3Cが定めるWeb標準仕様策定にウェブアクセシビリティの専門家として関わる。2010~2018年に人間中心設計専門家を保有、数年間ウェブアクセシビリティ基盤委員も務める。その後、不動産会社向けにSaaSを提供する企業の事業開発部で複数サービスを企画、ローンチ。CMSを提供し1000以上のサイトを分析。顧客サポート、サイト運営にも関わる。
2022年3月に独立後、2024年4月に株式会社BringFlowerを設立。SEOコンサルを活動の軸に据えつつ、AIライティングツールの開発と運営を自ら行う。グッドデザイン賞4件、ドイツユニバーサルデザイン賞2件、米国IDEA賞1件の受賞歴あり。