Skip to content

自定义字段

自定义字段概述

自定义字段(Custom Fields)是 WordPress 内置的元数据存储机制,允许为文章、页面添加额外信息。

基本使用场景

  • 文章阅读数
  • 产品价格
  • 项目链接
  • 作者信息
  • SEO 元描述
  • 特色内容标记

使用自定义字段

在后台启用

  1. 在文章编辑页面,点击右上角 "三个点" 菜单
  2. 选择 "选项"
  3. 启用 "自定义字段"
  4. 刷新页面即可看到自定义字段面板

基础操作

php
<?php
// 添加自定义字段
add_post_meta($post_id, 'key', $value, $unique = false);

// 获取自定义字段
$value = get_post_meta($post_id, 'key', $single = true);
// $single = true 返回字符串,false 返回数组

// 更新自定义字段
update_post_meta($post_id, 'key', $new_value, $old_value = '');

// 删除自定义字段
delete_post_meta($post_id, $key, $value = '');
?>

高级自定义字段 (ACF)

ACF 是最流行的自定义字段插件,提供图形化界面创建复杂字段组。

安装 ACF

bash
# 通过 WP-CLI 安装
wp plugin install advanced-custom-fields
wp plugin activate advanced-custom-fields

字段类型

字段类型说明
Text单行文本
Textarea多行文本
Number数字
Email邮箱地址
URL网址
Password密码
Wysiwyg Editor富文本编辑器
Image图片上传/选择
File文件上传/选择
Gallery多图画廊
Select下拉选择
Checkbox复选框
Radio Button单选按钮
True / False布尔值开关
Date Picker日期选择
Date Time Picker日期时间选择
Color Picker颜色选择器
Google Map地图选择
Relationship关联文章/页面
Post Object文章对象选择
User用户选择
Taxonomy分类选择
Repeater重复器(循环字段)
Flexible Content灵活内容
Clone克隆字段组

注册字段组

php
<?php
// functions.php 或插件文件

if (function_exists('acf_add_local_field_group')) {
    
    acf_add_local_field_group(array(
        'key' => 'group_portfolio_details',
        'title' => '作品详情',
        'fields' => array(
            array(
                'key' => 'field_client_name',
                'label' => '客户名称',
                'name' => 'client_name',
                'type' => 'text',
            ),
            array(
                'key' => 'field_project_url',
                'label' => '项目链接',
                'name' => 'project_url',
                'type' => 'url',
            ),
            array(
                'key' => 'field_project_year',
                'label' => '项目年份',
                'name' => 'project_year',
                'type' => 'number',
            ),
            array(
                'key' => 'field_featured',
                'label' => '精选项目',
                'name' => 'featured',
                'type' => 'true_false',
            ),
            array(
                'key' => 'field_gallery',
                'label' => '项目画廊',
                'name' => 'gallery',
                'type' => 'gallery',
                'mime_types' => 'jpg, png, webp',
            ),
        ),
        'location' => array(
            array(
                array(
                    'param' => 'post_type',
                    'operator' => '==',
                    'value' => 'portfolio',
                ),
            ),
        ),
    ));
    
}
?>

条件逻辑

php
<?php
array(
    'key' => 'field_conditional_field',
    'label' => '项目类型',
    'name' => 'project_type',
    'type' => 'select',
    'choices' => array(
        'website' => '网站',
        'app' => '应用程序',
        'other' => '其他',
    ),
),
array(
    'key' => 'field_app_store_url',
    'label' => 'App Store 链接',
    'name' => 'app_store_url',
    'type' => 'url',
    'conditional_logic' => array(
        array(
            array(
                'field' => 'field_project_type',
                'operator' => '==',
                'value' => 'app',
            ),
        ),
    ),
),
?>

Repeater 字段(重复器)

php
<?php
acf_add_local_field_group(array(
    'key' => 'group_team_members',
    'title' => '团队成员',
    'fields' => array(
        array(
            'key' => 'field_team_section_title',
            'label' => '章节标题',
            'name' => 'section_title',
            'type' => 'text',
        ),
        array(
            'key' => 'field_team_members',
            'label' => '成员列表',
            'name' => 'members',
            'type' => 'repeater',
            'layout' => 'row',  // row, block, table
            'sub_fields' => array(
                array(
                    'key' => 'field_member_name',
                    'label' => '姓名',
                    'name' => 'name',
                    'type' => 'text',
                ),
                array(
                    'key' => 'field_member_avatar',
                    'label' => '头像',
                    'name' => 'avatar',
                    'type' => 'image',
                    'preview_size' => 'thumbnail',
                    'return_format' => 'array',
                ),
                array(
                    'key' => 'field_member_role',
                    'label' => '职位',
                    'name' => 'role',
                    'type' => 'text',
                ),
                array(
                    'key' => 'field_member_bio',
                    'label' => '简介',
                    'name' => 'bio',
                    'type' => 'textarea',
                ),
            ),
        ),
    ),
    'location' => array(
        array(
            array(
                'param' => 'page',
                'operator' => '==',
                'value' => 'about-us',
            ),
        ),
    ),
));
?>

在模板中使用

php
<?php
// 基础字段
$client = get_field('client_name');
$url = get_field('project_url');
$featured = get_field('featured');

// 图片字段
$image = get_field('featured_image');
if ($image) {
    echo '<img src="' . $image['sizes']['medium'] . '" alt="' . $image['alt'] . '">';
}

// 重复器字段
if (have_rows('members')): ?>
    <div class="team-members">
        <?php while (have_rows('members')): the_row(); ?>
            <div class="member">
                <?php 
                $avatar = get_sub_field('avatar');
                if ($avatar): ?>
                    <img src="<?php echo $avatar['sizes']['thumbnail']; ?>" alt="">
                <?php endif; ?>
                <h3><?php the_sub_field('name'); ?></h3>
                <p><?php the_sub_field('role'); ?></p>
            </div>
        <?php endwhile; ?>
    </div>
<?php endif; ?>

灵活内容(Flexible Content)

php
<?php
// 定义灵活内容字段
acf_add_local_field_group(array(
    'key' => 'group_page_builder',
    'title' => '页面构建器',
    'fields' => array(
        array(
            'key' => 'field_page_content',
            'name' => 'page_content',
            'type' => 'flexible_content',
            'layouts' => array(
                array(
                    'key' => 'layout_hero',
                    'label' => 'Hero 区域',
                    'name' => 'hero',
                    'sub_fields' => array(
                        array(
                            'key' => 'field_hero_title',
                            'label' => '标题',
                            'name' => 'title',
                            'type' => 'text',
                        ),
                        array(
                            'key' => 'field_hero_image',
                            'label' => '背景图',
                            'name' => 'background_image',
                            'type' => 'image',
                        ),
                    ),
                ),
                array(
                    'key' => 'layout_features',
                    'label' => '功能列表',
                    'name' => 'features',
                    'sub_fields' => array(
                        array(
                            'key' => 'field_features_title',
                            'label' => '标题',
                            'name' => 'title',
                            'type' => 'text',
                        ),
                        array(
                            'key' => 'field_features_list',
                            'label' => '功能列表',
                            'name' => 'list',
                            'type' => 'repeater',
                            'sub_fields' => array(
                                array(
                                    'key' => 'field_feature_icon',
                                    'label' => '图标',
                                    'name' => 'icon',
                                    'type' => 'text',
                                ),
                                array(
                                    'key' => 'field_feature_text',
                                    'label' => '文字',
                                    'name' => 'text',
                                    'type' => 'text',
                                ),
                            ),
                        ),
                    ),
                ),
            ),
        ),
    ),
    'location' => array(
        array(
            array(
                'param' => 'page_template',
                'operator' => '==',
                'value' => 'template-builder.php',
            ),
        ),
    ),
));
?>

灵活内容模板

php
<?php
// page-builder.php
if (have_rows('page_content')) {
    while (have_rows('page_content')) {
        the_row();
        
        if (get_row_layout() === 'hero') {
            $title = get_sub_field('title');
            $bg = get_sub_field('background_image');
            ?>
            <section class="hero-section" style="background-image: url(<?php echo $bg['url']; ?>)">
                <h1><?php echo esc_html($title); ?></h1>
            </section>
            <?php
        }
        
        elseif (get_row_layout() === 'features') {
            $title = get_sub_field('title');
            ?>
            <section class="features-section">
                <h2><?php echo esc_html($title); ?></h2>
                <div class="features-grid">
                    <?php while (have_rows('list')): the_row(); ?>
                        <div class="feature-item">
                            <span class="icon"><?php the_sub_field('icon'); ?></span>
                            <span class="text"><?php the_sub_field('text'); ?></span>
                        </div>
                    <?php endwhile; ?>
                </div>
            </section>
            <?php
        }
    }
}
?>

选项页面

php
<?php
// 注册选项页面
acf_add_options_page(array(
    'page_title'    => '网站设置',
    'menu_title'    => '网站设置',
    'menu_slug'     => 'site-settings',
    'capability'    => 'manage_options',
    'redirect'      => false,
));

// 注册子选项页面
acf_add_options_sub_page(array(
    'page_title'    => '联系信息',
    'menu_title'    => '联系信息',
    'parent_slug'   => 'site-settings',
));
?>

获取选项页面数据

php
<?php
// 获取选项值
$phone = get_field('phone', 'option');
$email = get_field('email', 'option');
$address = get_field('address', 'option');

// 或使用简写
$settings = get_fields('option');

// 在模板中使用
echo get_option('phone', 'option'); // 需使用 get_option
?>

高级查询

php
<?php
// 查询有特定自定义字段的文章
$args = array(
    'post_type'  => 'product',
    'meta_query' => array(
        'relation' => 'AND',
        array(
            'key' => 'price',
            'value' => array(100, 500),
            'compare' => 'BETWEEN',
            'type' => 'NUMERIC',
        ),
        array(
            'key' => 'featured',
            'value' => '1',
            'compare' => '=',
        ),
    ),
    'orderby' => 'meta_value_num',
    'meta_key' => 'price',
);

$query = new WP_Query($args);

// meta_query 类型
// =, !=, >, <, >=, <=, LIKE, NOT LIKE, IN, NOT IN, BETWEEN, NOT BETWEEN
?>

CMB2(轻量替代方案)

CMB2 是 ACF 的免费替代品,适合不需要完整 ACF 功能的场景。

php
<?php
// 注册 CMB2 字段
function cmb2_portfolio_fields() {
    $cmb = new_cmb2_box(array(
        'id'           => 'portfolio_details',
        'title'        => '作品详情',
        'object_types' => array('portfolio'),
    ));
    
    $cmb->add_field(array(
        'name' => '客户名称',
        'id'   => 'client_name',
        'type' => 'text',
    ));
    
    $cmb->add_field(array(
        'name' => '项目链接',
        'id'   => 'project_url',
        'type' => 'text_url',
    ));
    
    $cmb->add_field(array(
        'name' => '项目年份',
        'id'   => 'project_year',
        'type' => 'text_small',
    ));
}
add_action('cmb2_init', 'cmb2_portfolio_fields');
?>

自定义字段最佳实践

  1. 使用有意义的键名 - 如 project_year 而非 year
  2. 添加前缀 - 避免与其他插件冲突,如 mfp_client_name
  3. 选择正确的字段类型 - 如 URL 用 url 类型而非 text
  4. 设置默认值 - 提供合理的默认值
  5. 添加验证规则 - 确保数据完整性
  6. 使用选项页面 - 存储全局设置
  7. 清理数据 - 删除插件时清理相关数据

相关资源

基于 WordPress官方文档 构建