経緯

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

ただ、これらを使うと、開発環境で構築したあと、本番環境に移すとき、また再設定しないといけないので、面倒くさいです。(DBフルダンプするとか、なんかしらのファイルを移行するとかでもいいかもしれませんが。

WordPressは出来る限りテーマで完結させて、WordPressのインストール自体はサーバ上で行って、テーマだけデプロイすればOKみたいにするのが好きです。

そこで、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 or 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){
    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));
    }
  }
}

まとめ

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

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

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' );
}

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文だけを記述して、いい感じにファイルを分けてやるのがスマートだと思います。