2026年5月24日

2026年5月24日

WordPressのCarbon Fieldsでカスタムフィールドをコード管理する方法

Carbon Fields は、カスタムフィールドを管理画面ではなく PHP のコードで定義するライブラリです。Composer で読み込み、Container::make() と Field::make() で入力欄を組み立て、carbon_get_post_meta() などの専用関数で値を取り出します。この記事では、導入からフィールド登録、テンプレートでの表示、保存形式の注意点、運用上の判断材料までを順に説明します。

Carbon Fields が向いているケース

ACF のように管理画面でフィールドを作る方式は手軽ですが、設定がデータベースに入るため、環境間の差分管理やレビューがしにくくなります。Carbon Fields はフィールドの定義がすべて PHP ファイルに書かれるので、Git で履歴を追え、ステージングと本番で同じ定義を揃えやすくなります。開発者がテーマやプラグインを管理しているサイトで、編集者はフィールドに入力するだけ、という体制に向いています。

逆に、エンジニアがいない体制で運用担当者がフィールドを追加・変更したい場合は、GUI のある ACF などのほうが適しています。また Carbon Fields は以前は WordPress.org のプラグインとしても配布されていましたが、現在は Composer で読み込む使い方が中心です。更新の頻度は時期によって差があるため、採用前に GitHub のリリース状況と、使っている WordPress・PHP のバージョンで動作報告があるかを確認してください(2026年10月現在)。

導入する場所を決める

フィールド定義はテーマではなく、サイト専用のプラグインか mu-plugin に置くことを勧めます。テーマに書くと、テーマを変えたときに入力欄が消え、保存済みのデータが管理画面から見えなくなるためです。ここでは wp-content/mu-plugins/site-fields/ に置く例で進めます。作業前にデータベースのバックアップを取り、ステージング環境で試してください。

mkdir -p wp-content/mu-plugins/site-fields
cd wp-content/mu-plugins/site-fields
composer require htmlburger/carbon-fields

mu-plugins はサブディレクトリ内のファイルを自動では読み込まないため、直下に読み込み用のファイルを置きます。

<?php
// wp-content/mu-plugins/site-fields-loader.php
require_once __DIR__ . '/site-fields/fields.php';

ライブラリを起動してフィールドを登録する

Carbon Fields は after_setup_theme で起動し、carbon_fields_register_fields フックの中でコンテナとフィールドを登録します。ここでは「book」という投稿タイプに書籍情報の入力欄を付ける例です。

<?php
// wp-content/mu-plugins/site-fields/fields.php
use Carbon_Fields\Container;
use Carbon_Fields\Field;

require_once __DIR__ . '/vendor/autoload.php';

add_action( 'after_setup_theme', function () {
    \Carbon_Fields\Carbon_Fields::boot();
} );

add_action( 'carbon_fields_register_fields', function () {
    Container::make( 'post_meta', '書籍情報' )
        ->where( 'post_type', '=', 'book' )
        ->add_fields( array(
            Field::make( 'text', 'book_isbn', 'ISBN' )
                ->set_help_text( 'ハイフンなしの13桁で入力' ),
            Field::make( 'date', 'book_release_date', '発売日' ),
            Field::make( 'select', 'book_format', '形態' )
                ->add_options( array(
                    'paper'  => '紙',
                    'ebook'  => '電子書籍',
                ) ),
            Field::make( 'complex', 'book_authors', '著者' )
                ->add_fields( array(
                    Field::make( 'text', 'name', '名前' ),
                    Field::make( 'text', 'role', '役割' ),
                ) ),
        ) );

    Container::make( 'theme_options', 'サイト設定' )
        ->add_fields( array(
            Field::make( 'text', 'site_contact_email', '問い合わせ先メール' ),
        ) );
} );

Container::make() の第1引数でどこに入力欄を出すかを決めます。投稿の post_meta のほか、ターム用の term_meta、ユーザー用の user_meta、独自の設定画面を作る theme_options などがあります。where() で表示条件を指定でき、投稿タイプ以外に固定ページのテンプレートや投稿 ID でも絞り込めます。

フィールド名は英小文字とアンダースコアで付け、ほかのプラグインと衝突しない接頭辞を付けておくと安全です。一度データが入ったあとで名前を変えると、既存の値は新しい名前からは読めなくなります。

テンプレートで値を表示する

値の取得には Carbon Fields の関数を使い、出力時にエスケープします。

<?php
// single-book.php のループ内
$isbn    = carbon_get_the_post_meta( 'book_isbn' );
$authors = carbon_get_the_post_meta( 'book_authors' );
$email   = carbon_get_theme_option( 'site_contact_email' );

if ( $isbn ) {
    echo '<p>ISBN: ' . esc_html( $isbn ) . '</p>';
}

if ( ! empty( $authors ) ) {
    echo '<ul class="book-authors">';
    foreach ( $authors as $author ) {
        printf(
            '<li>%s(%s)</li>',
            esc_html( $author['name'] ),
            esc_html( $author['role'] )
        );
    }
    echo '</ul>';
}

if ( $email && is_email( $email ) ) {
    echo '<a href="' . esc_url( 'mailto:' . $email ) . '">' . esc_html( $email ) . '</a>';
}

ループの外や別の投稿の値は carbon_get_post_meta( $post_id, 'book_isbn' ) のように投稿 ID を指定します。タームやユーザーには carbon_get_term_meta()、carbon_get_user_meta() があります。

保存形式と get_post_meta の違い

ここが Carbon Fields で最もつまずきやすい点です。単純なフィールドは、メタキーの先頭にアンダースコアが付いた形(例: _book_isbn)で保存されます。そのため get_post_meta( $id, 'book_isbn', true ) では値が取れません。

complex フィールドはさらに独特で、1つの配列としてではなく、行番号や子フィールド名を含む複数のメタキーに分けて保存されます。WP_Query の meta_query で並べ替えや絞り込みをしたい値は、complex の中に入れず、単独のフィールドにしておくほうが扱いやすくなります。正確なキーの形はバージョンによって変わりうるため、必要なときは wp post meta list <投稿ID> で実際の保存内容を確認してください。

また、Carbon Fields の取得関数は、フィールドの登録が終わる前に呼ぶと期待した値を返しません。init より早いタイミングや、carbon_fields_register_fields より前に実行されるコードから値を読む場合は、carbon_fields_fields_registered アクション以降に処理を回します。

ブロックエディターと REST API での扱い

post_meta コンテナはブロックエディターでは、本文の下のメタボックス領域に表示されます。サイドバーのパネルとしては出ないため、編集者には「入力欄は下にある」と案内しておくと混乱が減ります。Carbon Fields には独自ブロックを作る Block::make() もあり、入力欄とサーバー側の描画関数を組み合わせて簡単なブロックを作れます。

ヘッドレス構成などで REST API から値を読みたい場合は、フィールドごとに REST API への公開を設定する方法が用意されています。公開すると誰でも読める状態になりうるので、個人情報や内部用のメモを含むフィールドは公開しないでください。

運用で確認しておくこと

  • 更新前の確認: Composer で Carbon Fields を更新する前にステージングで管理画面の保存と表示を確認する。保存処理が壊れると入力内容が失われることがある
  • ACF との併用: 同じメタキー名を両方で使わない。片方の保存が他方の値を上書きする
  • データの移行: 別の仕組みに乗り換えるときは、保存形式の違いを踏まえて移行スクリプトを書く必要がある。特に complex の値は変換の手間が大きい
  • 権限: 入力欄の表示・保存の権限は投稿の編集権限に従う。設定画面(theme_options)は管理者だけが触れる前提で設計する

まとめ

  • Carbon Fields はフィールド定義を PHP で書くライブラリで、Git での差分管理や環境間の統一に向く
  • 定義はテーマではなく mu-plugin かサイト専用プラグインに置き、after_setup_theme で起動、carbon_fields_register_fields で登録する
  • 値は carbon_get_the_post_meta() などで取得し、esc_html() / esc_url() でエスケープして出力する
  • 保存キーの先頭にアンダースコアが付き、complex は複数のメタキーに分かれる。並べ替えに使う値は単独フィールドにする
  • 更新状況を確認してから採用し、更新はステージングで保存と表示を確かめてから行う

お気軽にご相談ください

お見積りへ お問い合わせへ
▲