WordPress 自定義字段與後台 Meta Box 完整開發指南
WordPress 透過 add_post_meta() 儲存自定義字段,配合 add_meta_box() 在後台編輯頁建立專屬輸入區塊,是主題與外掛開發的核心技能。本文詳細解析兩函數用法並提供完整實作範例。
一、add_post_meta() — 程式化新增自定義字段
函數簽名
add_post_meta( $post_id, $meta_key, $meta_value, $unique = false )
參數說明
| 參數 | 類型 | 必要 | 說明 |
| $post_id | int | 是 | 文章/頁面 ID |
| $meta_key | string | 是 | 字段鍵名(如 _postviews、_thumbnail_id) |
| $meta_value | mixed | 是 | 字段值(陣列會自動序列化) |
| $unique | bool | 否 | true=不允許同鍵名重複,false=允許(預設) |
使用範例
<?php
// 新增單一值(不允許重複)
add_post_meta(1, '_postviews', '99', true);
// 允許重複鍵名
add_post_meta(1, '_postviews', '999', false);
// 讀取驗證
var_dump(get_post_meta(1));
// 輸出:
// array(1) { ["_postviews"]=> array(2) { [0]=> string(2) "99" [1]=> string(3) "999" } }
// 再次新增同鍵名且 unique=true → 不會新增
add_post_meta(1, '_postviews', '996', true);
add_post_meta(1, '_postviews', '997', true);
var_dump(get_post_meta(1));
// 仍只有第一筆 996
常見應用場景
- 文章瀏覽計數(
_postviews)
- SEO 外掛儲存 title/description/keywords
- 自定義縮圖、下載連結、價格等業務字段
二、add_meta_box() — 後台編輯頁新增設定區塊
函數簽名
add_meta_box(
$id, // HTML id 屬性
$title, // 區塊標題
$callback, // 顯示內容的回調函數
$post_type, // 'post'、'page' 或自定義文章類型
$context, // 'normal'、'advanced'、'side' 顯示位置
$priority, // 'high'、'core'、'default'、'low' 優先級
$callback_args // 傳遞給回調的額外參數
);
參數詳解
| 參數 | 說明 | 常用值 |
| $context | 顯示區域 | normal(主編輯區下方)、side(側邊欄)、advanced(底部) |
| $priority | 優先級(高者靠上) | high、default、low |
完整實作範例
<?php
// 1. 掛載:在 'add_meta_boxes' 勾子註冊
function add_xz_box() {
add_meta_box(
'xz_box_1', // id
'自定義設定區塊', // 標題
'xz_box_1_callback', // 回調
'post', // 文章類型
'side', // 側邊欄
'high', // 高優先級
array('str1', 'str2') // 額外參數
);
}
add_action('add_meta_boxes', 'add_xz_box');
// 2. 回調函數:輸出表單欄位
function xz_box_1_callback($post, $boxargs) {
// 顯示隱藏 nonce 欄位(安全驗證)
wp_nonce_field('xz_box_save', 'xz_box_nonce');
// 獲取已儲存值
$value = get_post_meta($post->ID, '_xz_field', true);
// 輸出表單
echo '<label for="xz_field">自定義輸入:</label>';
echo '<input type="text" id="xz_field" name="xz_field" value="' . esc_attr($value) . '" class="widefat" />';
echo '<p class="description">說明文字</p>';
// 使用額外參數
echo '<p>參數1: ' . esc_html($boxargs['args'][0]) . '</p>';
echo '<p>參數2: ' . esc_html($boxargs['args'][1]) . '</p>';
}
// 3. 儲存:掛載到 'save_post' 勾子
function save_xz_box($post_id) {
// 安全檢查
if (!isset($_POST['xz_box_nonce']) || !wp_verify_nonce($_POST['xz_box_nonce'], 'xz_box_save')) return;
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
if (!current_user_can('edit_post', $post_id)) return;
// 儲存資料
if (isset($_POST['xz_field'])) {
update_post_meta($post_id, '_xz_field', sanitize_text_field($_POST['xz_field']));
}
}
add_action('save_post', 'save_xz_box');
三、進階:移除預設 Meta Box
function remove_default_meta_boxes() {
remove_meta_box('postcustom', 'post', 'normal'); // 自定義字段
remove_meta_box('postexcerpt', 'post', 'normal'); // 摘要
remove_meta_box('trackbacksdiv', 'post', 'normal'); // 引用通告
remove_meta_box('commentstatusdiv', 'post', 'normal'); // 討論
remove_meta_box('commentsdiv', 'post', 'normal'); // 評論
remove_meta_box('slugdiv', 'post', 'normal'); // 別名
remove_meta_box('authordiv', 'post', 'normal'); // 作者
}
add_action('admin_menu', 'remove_default_meta_boxes');
四、最佳實踐總結
| 場景 | 推薦函數 | 關鍵點 |
| 程式批量寫入 | add_post_meta() | $unique=true 避免重複;陣列值自動序列化 |
| 後台提供輸入介面 | add_meta_box() | 必須配合 save_post 驗證 nonce、權限、清洗輸入 |
| 前台顯示 | get_post_meta() | 第三參數 true 回傳單值,false 回傳陣列 |
| 區塊編輯器支援 | register_meta() + REST API | Gutenberg 時代標準做法,傳統 Meta Box 仍相容 |
安全鐵律:所有儲存操作必須驗證 wp_verify_nonce()、檢查 current_user_can()、清洗輸入 sanitize_text_field(),否則會有 CSRF 與 XSS 風險。