MENU CLOSE

【WordPress】
Smart Custom Fieldsを
コード定義で管理する

WordPress
WordPress

Smart Custom Fieldsとは?

Smart Custom Fields(スマートカスタムフィールズ)はWordPressのカスタムフィールドを使いやすく拡張してくれるプラグインです。

Smart Custom Fields

https://ja.wordpress.org/plugins/smart-custom-fields/

カスタムフィールドの拡張プラグインは有名どころでは他に、

などがあります。

Smart Custom Fieldsの特徴としては、Advanced Custom Fieldsではpro版(有料)でないと使えないループ機能が使えるオプションページが作れるfunctions.phpにコードでカスタムフィールドを定義しておける、などがあります。

今回記事としてメモしておきたいのが「コードでカスタムフィールドを定義しておける」という部分なので、それについてを書きます。
Smart Custom Fieldsのそもそもの使い方については、簡単なので公式プラグインページ作者のページを参考にしてみると良いです。

フィルターフック

smart-cf-register-fieldsというフィルターフックを使ってfunctions.php内にカスタムフィールドを定義します。

/**
 * カスタムフィールドを定義
 * 
 * @param array  $settings  MW_WP_Form_Setting オブジェクトの配列
 * @param string $type      投稿タイプ or ロール
 * @param int    $id        投稿ID or ユーザーID
 * @param string $meta_type post | user
 * @return array
 */
function my_add_meta_box( $settings, $type, $id, $meta_type )
{
  //ユーザープロフィール画面を判定
  switch ($meta_type) {
    case 'user':
    $settings = add_meta_box_author($settings, $id);
    break;

    default:
    break;
  }

  //投稿タイプで判定
  switch($type) {
    //投稿ページ
    case 'post':
    $settings = add_meta_box_posts($settings, $id);
    break;

    //固定ページ
    case 'page':
    $settings = add_meta_box_pages($settings, $id);
    break;
    

    default:
    break;
  }
  return $settings;
}
add_filter( 'smart-cf-register-fields', 'my_add_meta_box', 10, 4 );

このフックを使うと、引数が4つ取れるので、それによって管理画面のどのページにどのカスタムフィールドを定義するかを細かくコードで条件分岐することが可能になります。 サンプルで書いたPHPのswitch構文はちょっと・・・って方は各自書き換えてください。
条件分岐内のadd_meta_box_authoradd_meta_box_postsなどの関数については後述します。

個人的にはこのフィルターフック機能がSmart Custom Fieldsを選んでいる理由のひとつです。
他のプラグインではカスタムフィールドを表示するページを細かく制御できない場合があり、表示させたくないページに全然関係ないフィールドが表示されてしまう、といったことがあります。
例をあげると、「フロントページの子ページのみにカスタムフィールドを追加したい」というように条件が少し複雑になると、プラグインに標準で付いている表示条件ではうまく設定できない場合があります。

これがコードベースだと上記のサンプルコードのようにテンプレート作成と同じく条件分岐すればいいだけなので、とても簡単に設定できます。

例はちょっと極端な条件でしたが、いろんなページでたくさんのカスタムフィールドを扱うサイトの場合になると、必要なページに必要な入力エリアだけを用意してあげるのもWordPressテーマを制作する上で必要なことだと思います。

また、一度コードで定義しておけば同じようなカスタムフィールドは他のテーマへの流用ができるため、今後のテーマ作成が捗ります。

少し脱線しましたが、コードに戻ります。

フィールドを定義する

SEOグループとして「タイトル」「ディスクリプション」「noindex」「OGP画像」のカスタムフィールドを作ってみます。

function add_scf_seo_group(){
  //SCF::add_setting( 'ユニークなID', 'メタボックスのタイトル' );
  $setting = SCF::add_setting( 'meta_box_seo', 'SEO' );
  // $setting->add_group( 'ユニークなID', 繰り返し可能か, カスタムフィールドの配列 );
  $setting->add_group('cf_seo_group', false,
    [
      [
        'name'    => 'cf_title',
        'label'   => 'タイトル',
        'type'    => 'text',
        'notes'   => '30文字前後'
      ],
      [
        'name'    => 'cf_description',
        'label'   => 'ディスクリプション',
        'type'    => 'textarea',
        'rows'    => 5,
        'notes'   => '120文字前後'
      ],
      [
        'name'    => 'cf_noindex',
        'label'   => '検索結果に表示させる',
        'type'    => 'boolean'
      ],
      [
        'name'    => 'cf_ogp',
        'label'   => 'OGP画像',
        'type'    => 'image',
        'notes'   => '横1200×縦630',
        'size'    => 'large'
      ]
    ]
  );
  return $setting;
}

管理画面から新規作成する場合は対応するものを選択して入力するだけですが、コードになると配列でオプションを追加していくような書き方になります。

オプションの書き方については、Qiitaにまとめている方がおられるのでそちらの記事を参考にすると良いかと思います。

SmartCustomFieldsのコードでの定義についてのまとめ

https://qiita.com/yousan/items/7cbd56308ecc0e2bb263

書き方は好き嫌いによるところもありますが、1つの役割を持ったフィールドグループごとに関数を分けて書いておくと便利です。例えばサンプルの「SEO」グループにはSEO関連のカスタムフィールドだけ入れておき、それ以外のフィールドは別のグループとして切り分けておきます。そうして細分化しておくとコードベースで管理するメリットが出てきます。

例として「よくある質問」を追加する場合は、シンプルに質問と答えのカスタムフィールドを括ったよくある質問グループを作って、ループをオンにしておけば必要な数だけ追加できる汎用的なカスタムフィールドとなります。またこのコードはグループ名・フィールド名・ラベル名だけ変えれば「お知らせ」など他の用途にすぐに流用できます。

function add_scf_faq_group(){
  $setting = SCF::add_setting( 'meta_box_faq', 'よくある質問' );
  $setting->add_group('cf_faq_group', true, //trueでループをオン
    [
      [
        'name'    => 'cf_faq_question',
        'label'   => '質問',
        'type'    => 'textarea',
        'rows'    => 2
      ],
      [
        'name'    => 'cf_faq_answer',
        'label'   => '答え',
        'type'    => 'textarea',
        'rows'    => 2
      ]
    ]
  );
  return $setting;
}

//add_scf_faq()を流用して使う
function add_scf_info_group(){
  $setting = SCF::add_setting( 'meta_box_info', 'お知らせ' );
  $setting->add_group('cf_info_group', true, 
    [
      [
        'name'    => 'cf_info_title',
        'label'   => 'タイトル',
        'type'    => 'textarea',
        'rows'    => 2
      ],
      [
        'name'    => 'cf_info_detail',
        'label'   => '詳細',
        'type'    => 'textarea',
        'rows'    => 2
      ]
    ]
  );
  return $setting;
}

管理画面からフィールドグループを作ると最初は簡単で手軽に思いますが、別の環境で同じようなカスタムフィールドを用意したいと思った時にコピーしたいだけなのにデータベースが絡んでくるので、画面を見ながら手動で入力したり、いちいちXMLでインポート・エクスポートしたり、DBごとコピーしたりと作業が大変になります。

その点コードベースで管理されていると、一度作っておけば新しいテーマを作る時には管理画面に入らずともコピペで作れます。開発者的には非常に楽です。本番環境とテスト環境で別のデータベースになっている場合でも対応できます。

条件分岐した管理画面ごとにフィールドグループを追加する

各カスタムフィールドの追加関数を作成したら、あとは条件に合わせてフィールドを管理画面に追加していきます。 先ほど飛ばしたadd_meta_box_authoradd_meta_box_postsなどの関数についてがこちらになります。

//ユーザープロフィール編集画面
function add_meta_box_author($settings, $id){
  //プロフィール画像フィールドグループを追加する
  $settings[] = add_scf_avatar_group();
  //SEOフィールドグループを追加する
  $settings[] = add_scf_seo_group();
  return $settings;
}


//投稿ページ編集画面
function add_meta_box_posts($settings, $id) {
  //関連記事
  $settings[] = add_scf_related_post_group();
  //SEO
  $settings[] = add_scf_seo_group();
  return $settings; 
}

//固定ページ編集画面
function add_meta_box_pages($settings, $id) {
  //SEO
  $settings[] = add_scf_seo_group();
  
  //記事取得
  $post = get_post($id);
  if(!empty($post)){
    //親ページID
    $parent_id = $post->post_parent;
    //フロントページID取得
    $frontpage_id = intval(get_option( 'page_on_front' ));
    //フロントページの子ページの場合のみ
    if($parent_id === $frontpage_id){
      //お知らせフィールドグループを追加する
      $settings[] = add_scf_info_group();
    }
  }
  
  return $settings; 
}

ユーザープロフィール編集画面にはプロフィール画像のカスタムフィールド(サンプルコードはありません)と、先ほどサンプルで作ったSEOカスタムフィールドを追加しています。

同じ要領で投稿ページ、固定ページにも追加していますが、固定ページには前述で例に示した条件で「フロントページの子ページの場合のみにお知らせカスタムフィールドグループを追加する」として実装してみました。

注意点

条件分岐を複雑にした場合、新規作成時に一度「下書き保存」しないとカスタムフィールドが表示されない場合があります
例えばA・B・Cというカテゴリーがある投稿ページで「カテゴリーがAの時のみカスタムフィールドを追加する」という条件にした場合などです。
新規作成時はカテゴリーが選択されていないので、フィルターフックで設定している条件分岐に当てはまらないので表示されません。その場合はカテゴリを一旦選んで下書き保存し、管理画面をリロードすればフィールドが追加されます。

おわりに

コード定義できるようになってからSmart Custom Fieldsしか使っていないくらい、このプラグインには本当にお世話になっています。
コードを工夫すれば、プルダウンなど選択式のカスタムフィールドに動的に値を設定したりいろいろとカスタマイズできます。とてもおすすめです。

記事一覧

RELATED

テキストの無限ループアニメーション【CSS + JS】
inoue
inoueのサムネイル
TIPS

【CSS + JS】テキストの無限ループアニメーション

shopify
inoue
inoueのサムネイル
TIPS

【Shopify】カートへの遷移を飛ばしてチェックアウトに進むボタンを設置する

PhotoSwipe v5
inoue
inoueのサムネイル
TIPS

【JS】PhotoSwipe v5を使って画像をポップアップ表示する

AVIF [ gulpでjpg・pngからAVIF画像を生成 ]
inoue
inoueのサムネイル
TIPS

gulpでjpg・pngからAVIF画像を生成する

MutationObserverでDOMを監視[PhotoSwipe(v5)+Swiper(v8)連携]
inoue
inoueのサムネイル
TIPS

【JS】MutationObserverでDOMを監視[PhotoSwipe(v5)+Swiper(v8)連携]

Google Sheets API スプレッドシートのデータをJSONで取得する
inoue
inoueのサムネイル
TIPS

【Google Sheets API】 スプレッドシートのデータをJSONで取得する

NEW POSTS

GA4連携人気記事ランキング機能を自作プラグイン化してみ【WordPress】
inoue
inoueのサムネイル
TRY

【WordPress】GA4連携の人気記事ランキング機能を自作プラグイン化してみた

netlify UPDATE BUILD IMAGE [ビルドイメージの更新]
inoue
inoueのサムネイル
TRY

【netlify】ビルドイメージを更新 [ Ubuntu Xenial 16.04 → Ubuntu Focal 20.04 ]

Google Business Profile API [ PHPでクチコミ一覧取得 ]
inoue
inoueのサムネイル
TIPS

【PHP】Google Business Profile APIを使ってクチコミを取得する

screendot screenshot API
inoue
inoueのサムネイル
TRY

スクリーンショットのAPI「screendot」を使ってみた

window.matchMedia hoverを判定
inoue
inoueのサムネイル
TIPS

【window.matchMedia】メディアクエリでhoverが使えるデバイスを判定

lax.js
inoue
inoueのサムネイル
TIPS

lax.jsの使い方【スクロール連動アニメーションの実装】

ブログ記事一覧
  • HOME
  • TIPS
  • 【WordPress】Smart Custom Fieldsをコード定義で管理する