カスタムフィールドでデータを一覧する、または入力する際にまとめてやってしまいたいことがあります。
例えば有料記事の価格なのですが、管理画面に専用メニューを作ると時短になります。

本記事ではその作り方を紹介いたします。
ちなみにいろいろな技術記事を書いていますので、よかったら見てくださいませ。
目次
WordPressの管理画面にカスタムフィールドの一覧・編集機能を作成する方法
まずはカスタムフィールドを用意しましょう。
今回は価格(price)というカスタムフィールドを作成します。
いつもであればACFかSCFのプラグインでカスタムフィールドを作成するのですが、一つであればfunctions.phpで書いてしまいます。
カスタムフィールドの作成
functions.phpに下記のコードを挿入します。
// 投稿画面にカスタムフィールドエリアを追加
add_action('admin_menu', function () {
add_meta_box(
'custom_price_box',
'価格',
'render_custom_price_field',
'post',
'side',
'default'
);
});
// 入力欄の出力
function render_custom_price_field($post)
{
wp_nonce_field('save_custom_price', 'custom_price_nonce');
$price = get_post_meta($post->ID, 'price', true);
echo '<label for="price">価格(円)</label>';
echo '<input type="number" id="price" name="price" value="' . esc_attr($price) . '" style="width:100%;" />';
}
// 保存処理
add_action('save_post', function ($post_id) {
if (!isset($_POST['custom_price_nonce']) || !wp_verify_nonce($_POST['custom_price_nonce'], 'save_custom_price')) return;
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
if (isset($_POST['price'])) {
update_post_meta($post_id, 'price', sanitize_text_field($_POST['price']));
}
});
カスタムフィールドの表示場所
コードにsideと設定した場合はサイドバーにカスタムフィールドが設置されます。

逆にnomalとした場合は編集記事下にカスタムフィールドが設置されます。

専用管理画面の作成
下記のコードをfunctions.phpに記載するだけです。
一応、記事が多い場合を想定してカテゴリーとタグの絞り込みもつけておきました。
以下のコードです。
名称は好きに変更しましょう。
このコードをベースにAIで書き換えてもよいでしょう。
add_action('admin_menu', function () {
add_menu_page(
'価格一覧',
'価格一覧',
'manage_options',
'custom-price-list',
'render_custom_price_list',
'dashicons-money-alt',
20
);
});
function render_custom_price_list()
{
// カテゴリーとタグの取得
$categories = get_terms(['taxonomy' => 'category', 'hide_empty' => false]);
$tags = get_terms(['taxonomy' => 'post_tag', 'hide_empty' => false]);
// 選択されたID
$selected_cat = isset($_GET['cat_id']) ? intval($_GET['cat_id']) : 0;
$selected_tag = isset($_GET['tag_id']) ? intval($_GET['tag_id']) : 0;
// 投稿を取得
$args = [
'post_type' => 'post',
'posts_per_page' => 100,
'post_status' => 'publish',
'tax_query' => [],
];
if ($selected_cat) {
$args['tax_query'][] = [
'taxonomy' => 'category',
'field' => 'term_id',
'terms' => $selected_cat,
];
}
if ($selected_tag) {
$args['tax_query'][] = [
'taxonomy' => 'post_tag',
'field' => 'term_id',
'terms' => $selected_tag,
];
}
if (count($args['tax_query']) > 1) {
$args['tax_query']['relation'] = 'AND'; // 両方一致した投稿に限定
}
$posts = get_posts($args);
// 保存処理
if (isset($_POST['custom_price_save']) && isset($_POST['price']) && is_array($_POST['price'])) {
foreach ($_POST['price'] as $post_id => $price) {
update_post_meta($post_id, 'price', sanitize_text_field($price));
}
echo '<div class="updated"><p>価格を保存しました。</p></div>';
}
echo '<div class="wrap">';
echo '<h1>投稿の価格一覧</h1>';
// ▼絞り込みフォーム(カテゴリ + タグ)
echo '<form method="get" style="margin-bottom: 1em;">';
echo '<input type="hidden" name="page" value="custom-price-list">';
echo '<label for="cat_id">カテゴリー:</label>';
echo '<select name="cat_id" id="cat_id">';
echo '<option value="0">すべて</option>';
foreach ($categories as $cat) {
$selected = selected($selected_cat, $cat->term_id, false);
echo "<option value='{$cat->term_id}' {$selected}>{$cat->name}</option>";
}
echo '</select> ';
echo '<label for="tag_id">タグ:</label>';
echo '<select name="tag_id" id="tag_id">';
echo '<option value="0">すべて</option>';
foreach ($tags as $tag) {
$selected = selected($selected_tag, $tag->term_id, false);
echo "<option value='{$tag->term_id}' {$selected}>{$tag->name}</option>";
}
echo '</select> ';
echo '<button type="submit" class="button">絞り込み</button>';
echo '</form>';
// ▼価格編集テーブル
echo '<form method="post">';
echo '<table class="widefat fixed striped">';
echo '<thead><tr><th style="max-width:400px;width:400px;">記事タイトル</th><th>価格</th></tr></thead><tbody>';
foreach ($posts as $post) {
$price = get_post_meta($post->ID, 'price', true);
echo '<tr>';
echo '<td style="max-width:400px;width:400px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">';
echo '<a href="' . get_edit_post_link($post->ID) . '">' . esc_html($post->post_title) . '</a>';
echo '</td>';
echo '<td><input type="number" name="price[' . $post->ID . ']" value="' . esc_attr($price) . '" /></td>';
echo '</tr>';
}
echo '</tbody></table>';
submit_button('価格を保存する', 'primary', 'custom_price_save');
echo '</form>';
echo '</div>';
}
以上です。
あとは管理画面から確認しましょう。

シンプル版
絞り込みなしのシンプル版も作成しました。

add_action('admin_menu', function () {
add_menu_page(
'価格一覧',
'価格一覧',
'manage_options',
'custom-price-list',
'render_custom_price_list',
'dashicons-money-alt',
20
);
});
function render_custom_price_list()
{
// 投稿を取得(100件まで表示)
$posts = get_posts([
'post_type' => 'post',
'posts_per_page' => 100,
'post_status' => 'publish',
]);
// 保存処理
if (isset($_POST['custom_price_save']) && isset($_POST['price']) && is_array($_POST['price'])) {
foreach ($_POST['price'] as $post_id => $price) {
update_post_meta($post_id, 'price', sanitize_text_field($price));
}
echo '<div class="updated"><p>価格を保存しました。</p></div>';
}
echo '<div class="wrap">';
echo '<h1>投稿の価格一覧</h1>';
echo '<form method="post">';
echo '<table class="widefat fixed striped">';
echo '<thead><tr><th>記事タイトル</th><th>価格</th></tr></thead><tbody>';
foreach ($posts as $post) {
$price = get_post_meta($post->ID, 'price', true);
echo '<tr>';
echo '<td><a href="' . get_edit_post_link($post->ID) . '">' . esc_html($post->post_title) . '</a></td>';
echo '<td><input type="number" name="price[' . $post->ID . ']" value="' . esc_attr($price) . '" /></td>';
echo '</tr>';
}
echo '</tbody></table>';
submit_button('価格を保存する', 'primary', 'custom_price_save');
echo '</form>';
echo '</div>';
}
この記事で紹介しているコードは、GitHubのMOTOKI-LLC/WAZA-codeにもまとめています。



