カスタムフィールド管理プラグイン「Advanced Custom Fields(ACF)」では、通常は管理画面からフィールドグループを追加します。しかし、プロジェクトが大規模になると管理画面操作だけでは再現性や差分管理が難しくなります。
そこでおすすめなのが コードでフィールドグループを定義して管理 する方法です。
コード管理のメリット
- Gitで差分管理できる
→ 誰がどんなフィールドを追加・変更したか明確になります。 - 環境ごとの差異がなくなる
→ 開発環境と本番環境で設定がずれるリスクを回避。 - 複数人開発に強い
→ GUI操作の手戻りがなく、コードレビューも可能。
ディレクトリ構成
テーマ内に「functions/advanced-custom-fields/」ディレクトリを作り、フィールドグループごとにファイルを分割して管理します。
/wp-content/themes/xxxxx/
├─ functions/
│ ├─ functions.php
│ └─ advanced-custom-fields/
│ ├─ loader.php ← ローダー本体
│ ├─ groups/ ← グループ定義ファイルを格納
│ │ ├─ 10-banner.php
│ │ └─ 20-hero.php
│ └─ parts/ ← 共通フィールド部品(任意)
│ └─ link-field.php
- loader.php … groups以下のファイルを自動読み込み
- groups/ … フィールドグループ定義をファイルごとに配置
- parts/ … 共有フィールド(リンクURLなど)を部品化する場合
ローダーの実装例
functions.php
から loader.php を読み込み、acf/init
フックで groups/*.php を一括登録します。
// functions.php の抜粋
$acf_loader = get_theme_file_path('/functions/advanced-custom-fields/loader.php');
if (file_exists($acf_loader)) {
require_once $acf_loader;
}
<?php
// loader.php
add_action('acf/init', function () {
if (!function_exists('acf_add_local_field_group')) return;
$groups_dir = __DIR__ . '/groups';
if (!is_dir($groups_dir)) return;
$files = glob($groups_dir . '/*.php');
natsort($files);
foreach ($files as $file) {
$result = include $file;
if (empty($result)) continue;
// 単一グループ or 複数グループ対応
if (isset($result['key'])) {
$groups = [$result];
} elseif (isset($result[0]['key'])) {
$groups = $result;
} else {
continue;
}
foreach ($groups as $group) {
if (isset($group['key'], $group['title'], $group['fields'], $group['location'])) {
acf_add_local_field_group($group);
}
}
}
});
フィールドグループ定義ファイル(例:バナー情報)
<?php
// groups/10-banner.php
if (!defined('ABSPATH')) exit;
return [
'key' => 'group_banner_info',
'title' => 'バナー情報',
'fields' => [
[
'key' => 'field_banner_icon',
'label' => 'アイコン画像(SVG可)',
'name' => 'banner_icon',
'type' => 'image',
'return_format' => 'array',
'preview_size' => 'thumbnail',
'mime_types' => 'svg,png,jpg,jpeg,webp,gif',
],
[
'key' => 'field_banner_url',
'label' => 'リンクURL',
'name' => 'banner_url',
'type' => 'text', // # や相対パスも可
'placeholder' => '#',
],
[
'key' => 'field_banner_status',
'label' => '掲載ステータス',
'name' => 'banner_status',
'type' => 'true_false',
'ui' => 1,
'message' => '掲載する',
'default_value' => 0, // デフォルトは「いいえ」
],
[
'key' => 'field_banner_start',
'label' => '掲載開始',
'name' => 'banner_start',
'type' => 'date_picker',
'display_format' => 'Y-m-d',
'return_format' => 'Y-m-d',
'conditional_logic' => [[['field' => 'field_banner_status','operator' => '==','value' => '1']]],
],
[
'key' => 'field_banner_end',
'label' => '掲載終了',
'name' => 'banner_end',
'type' => 'date_picker',
'display_format' => 'Y-m-d',
'return_format' => 'Y-m-d',
'conditional_logic' => [[['field' => 'field_banner_status','operator' => '==','value' => '1']]],
],
],
'location' => [
[[
'param' => 'post_type',
'operator' => '==',
'value' => 'mo_side_banner',
]],
],
];
共有パーツの利用
同じようなフィールドを複数グループで使う場合、parts/
に切り出して include
すれば再利用できます。
// parts/link-field.php
return [
'key' => 'field_common_link_url',
'label' => 'リンクURL',
'name' => 'common_link_url',
'type' => 'text',
'placeholder' => '#',
];
運用の注意点
- キー(field_, group_)は全体でユニークにする
→ 衝突すると上書きされてしまいます。 - Gitでレビューできるようにする
→ フィールド追加もコードレビューの対象に。 - 開発/本番で切替たい場合
→WP_ENVIRONMENT_TYPE
を参照して、loader.php で条件分岐可能。 - 必要なら ACF JSON を併用
→ コードベースを主に、GUIで編集 → JSON エクスポートで補助的に管理も可能。
まとめ
- ACF の設定は GUI だけでなく コードで管理する方がチーム開発に向いている
- loader.php + groups ディレクトリ 方式でフィールドグループを分割管理できる
- 再利用フィールドは parts/ に切り出すと効率的
これで「どの環境でも同じフィールドグループが再現できる」ようになり、開発効率と安定性が格段に上がります。
コメント