[WordPress] functions.phpでカスタムフィールドを固定させる方法

WordPressのカスタムフィールドは使いにくいので、それを解決するための様々なプラグインがあります。

ただ、これらを使うと、開発環境で構築したあと、本番環境に移すとき、再設定する必要があります。

個人的に、WordPressは出来る限りテーマで完結させて、サーバ上でWordPressをインストールして、テーマだけデプロイできるようにするのが好きです。

そこで、WordPressのカスタムフィールドをfunctions.phpで作成する方法についてまとめておこうと思います。

やり方

この記事では以下のようなフォームを作っていこうと思います。

フィールド名 タイプ
composer text
lyrics textarea

ファイルを分ける

カスタムフィールドを作ろうとすると、それなりにコードの行数が増えるので、functions.phpではinclude分だけを書いて、ファイルを分けてしまうのがいいと思います。
例)

<?php
include('admin/custom_field.php');
<?php
// このファイルにカスタムフィールドに関わる記述を書いていく。

カスタムフィールドのフォームを作る

画面に表示するようにフックを作成

<?php
add_action('admin_menu', 'add_music_field');

これは管理画面が表示される際にフックされる関数を指定するものです。ここでは、「管理画面が表示されるときにadd_music_fieldという関数を実行してね!」と言っています。

ボックスを作成

では、実際に実行するadd_music_fieldを定義していきましょう。

<?php
// 前略
// 以下を追記
function add_about_field() {
  // add_meta_box(表示されるボックスのHTMLのID, ラベル, 表示する内容を作成する関数名, 投稿タイプ, 表示方法)
  add_meta_box( 'music-composer','作曲者', 'create_form_music_composer', 'page', 'normal' );
  add_meta_box( 'music-lyrics','歌詞', 'create_form_music_lyrics', 'page', 'normal' );
}

add_meta_boxは投稿画面の「タグ」や「カテゴリー」みたいな一つの箱を作るものです。

大事なのは第3〜5引数です。

第3引数では表示する内容を作成する関数名を指定します。ここで指定した関数でHTMLを表示します。

第4引数は”page”, “post”, “custom_post_type”のslugを設定します。他にもdashboardなど指定はできますが、これらは投稿画面以外に使われるものなので、今回の用途ではこれらの3つくらいしか使わないと思います。
第5引数は’normal’, ‘side’, ‘advanced’の3種類選択できますが、これらは表示位置が変わります。具体的にどうなるのかは試してみてもらえればと思います。

HTMLを出力

以下のようにフォームのHTMLを出力する部分を作っていきます。

<?php
// 前略
// ここから追記
function create_form_music_composer(){
  global $post;
  echo '<input name="composer" style="width: 100%;" value="'.get_post_meta($post->ID,'composer',true).'"/>';
}
function create_form_music_lyrics(){
  global $post;
  echo '<textarea name="lyrics" style="width: 100%; height: 200px;">'.get_post_meta($post->ID, 'lyrics', true).'</textarea>'
  // WYSIWYGエディタを使うときは以下のコードを記述
  // wp_editor( get_post_meta($post->ID,'lyrics',true), 'lyrics-box', ['textarea_name' => 'lyrics'] );
}

ここで、global $post$postを使うために必要なので、書いておきましょう。ここまで、やっておけば、投稿画面にフォームが表示されると思います。

保存するためのコードを記述

投稿画面にフォームが表示されましたが、まだ、投稿しても保存はされません。

投稿されたとき、ちゃんと保存されるようにコードを書きましょう。

投稿された時のフックを作成

<?php
// 前略
// 以下を追加
add_action('save_post', 'save_music_field');

こうすることで、投稿を保存するときはsave_music_field関数を実行されます。

この関数の中で、カスタムフィールドを保存する処理を記述しましょう。

カスタムフィールドを保存

以下のようにすれば、カスタムフィールドを保存できます。配列には作ったフォームのname属性を記述しましょう。

<?php
// 前略
// ここから追記
function save_music_field($post_id){
  $my_fields = ['composer', 'lyrics'];
  foreach($my_fields as $my_field){
    // $valueに保存する値を格納する
    if(isset($_POST[$my_field])){
      $value=$_POST[$my_field];
    }else{
      $value='';
    }
    // $valueがもともと格納されているときはupdateしない
    // $valueが空のときは削除する
    if( strcmp($value, get_post_meta($post_id, $my_field, true)) != 0 ){
      update_post_meta($post_id, $my_field, $value);
    }elseif($value == ""){
      delete_post_meta($post_id, $my_field, get_post_meta($post_id, $my_field, true));
    }
  }
}

まとめ

まとめると、以下のようなadmin/custom_field.phpが出来上がります。

<?php
add_action('admin_menu', 'add_music_field');
function add_about_field() {
  add_meta_box( 'music-composer','作曲者', 'create_form_music_composer', 'page', 'normal' );
  add_meta_box( 'music-lyrics','歌詞', 'create_form_music_lyrics', 'page', 'normal' );
}

function create_form_music_composer(){
  global $post;
  echo '<input name="composer" style="width: 100%;" value="'.get_post_meta($post->ID,'composer',true).'"/>';
}
function create_form_music_lyrics(){
  global $post;
  echo '<textarea name="lyrics" style="width: 100%; height: 200px;">'.get_post_meta($post->ID, 'lyrics', true).'</textarea>'
  // WYSIWYGエディタを使うときは以下のコードを記述
  // wp_editor( get_post_meta($post->ID,'lyrics',true), 'lyrics-box', ['textarea_name' => 'lyrics'] );
}

add_action('save_post', 'save_music_field');
function save_music_field($post_id){
  $my_fields = ['composer', 'lyrics'];
  foreach($my_fields as $my_field){
    if(isset($_POST[$my_field])){
      $value=$_POST[$my_field];
    }else{
      $value='';
    }
    if( strcmp($value, get_post_meta($post_id, $my_field, true)) != 0 ){
      update_post_meta($post_id, $my_field, $value);
    }elseif($value == ""){
      delete_post_meta($post_id, $my_field, get_post_meta($post_id, $my_field, true));
    }
  }
}

これらを使えば、カスタムフィールドをプラグインに頼らず、テーマごとに作ることができます。

ご覧のとおり、コードが長くなるので、ファイルを分けてやらないと、管理が大変になってきますので、functions.phpinclude文だけを記述して、いい感じにファイルを分けてやるのがスマートだと思います。