WordPress函数:add_settings_section 创建设置区域

编辑文章

简介

在WordPress后台设置页面中创建逻辑分组区域,将相关的设置字段组织在一起,提升用户体验和管理界面清晰度。

语法

add_settings_section( string $id, string $title, callable $callback, string $page )

函数定义位于 wp-admin/includes/template.php,主要通过 do_settings_sections() 函数在页面渲染时调用显示。

参数 类型 必填 默认值 说明
$id string 区域唯一标识符(slug格式),用于内部引用
$title string 显示在区域顶部的标题文字
$callback callable 输出区域描述或其他HTML内容的回调函数
$page string 区域所属的设置页面slug(需与add_settings_field的page参数一致)

返回值:无返回值,函数直接注册区域到全局 $wp_settings_sections 数组中。

用法

基础用法

以下完整示例展示如何创建自定义设置页面并添加一个设置区域:

// 在主题的functions.php或插件文件中添加
add_action('admin_menu', 'myplugin_register_settings_page');
function myplugin_register_settings_page() {
    // 首先添加设置页面,区域将显示在此页面内
    add_options_page(
        '我的插件设置',          // 页面标题
        '我的插件',             // 菜单标题
        'manage_options',       // 权限要求
        'myplugin-settings',    // 页面slug(与add_settings_section的$page对应)
        'myplugin_settings_html' // 回调函数,输出页面HTML
    );
}

add_action('admin_init', 'myplugin_register_settings');
function myplugin_register_settings() {
    // 注册一个设置区域
    add_settings_section(
        'myplugin_basic_section',          // 区域ID
        '基础设置',                        // 区域标题
        'myplugin_section_description',    // 显示描述的回调函数
        'myplugin-settings'                // 所属页面slug,必须与add_options_page一致
    );

    // 通常在此函数内继续注册设置字段(add_settings_field)
}

// 区域描述回调函数
function myplugin_section_description() {
    echo '<p>这里是基础设置区域的说明文字,用于指导用户填写下面的字段。</p>';
}

// 设置页面HTML结构回调(由add_options_page指定)
function myplugin_settings_html() {
    // 检查用户权限
    if (!current_user_can('manage_options')) {
        return;
    }
    ?>
    <div class="wrap">
        <h1><?php echo esc_html(get_admin_page_title()); ?></h1>
        <form action="options.php" method="post">
            <?php
            // 输出设置区域和字段
            settings_fields('myplugin_options');  // 选项组名称
            do_settings_sections('myplugin-settings');  // 页面slug
            submit_button();
            ?>
        </form>
    </div>
    <?php
}

进阶用法

使用闭包作为回调函数

当描述逻辑简单且无需复用时,可以使用闭包减少函数定义:

add_action('admin_init', function() {
    add_settings_section(
        'myplugin_advanced_section',
        '高级配置',
        function() {
            // 闭包内部可以访问外部变量,但要注意作用域
            $help_link = 'https://example.com/docs';
            printf(
                '<p>如需更多帮助,请查看<a href="%s" target="_blank">官方文档</a>。</p>',
                esc_url($help_link)
            );
        },
        'myplugin-settings'
    );
});

动态生成区域标题

根据条件动态生成区域内容,例如多站点环境下的差异显示:

add_action('admin_init', 'myplugin_conditional_section');
function myplugin_conditional_section() {
    $section_title = '常规设置';

    if (is_multisite()) {
        $section_title = '网络设置(多站点)';
    }

    add_settings_section(
        'myplugin_network_section',
        $section_title,  // 动态标题
        function() {
            if (is_multisite()) {
                echo '<p>这些设置将应用于网络中的所有站点。</p>';
            } else {
                echo '<p>这些设置仅影响当前站点。</p>';
            }
        },
        'myplugin-settings'
    );
}

易错点

区域ID冲突

使用通用ID(如generaladvanced)可能导致与其他插件冲突。WordPress不会阻止重复ID注册,但后注册的会覆盖先注册的,导致区域丢失。

// 错误:ID太通用,易冲突
add_settings_section('general', '常规', 'callback', 'page');

// 正确:添加唯一前缀
add_settings_section('myplugin_general', '常规', 'callback', 'page');

忘记输出区域描述

注册了回调函数但没有在其中输出任何内容,用户会看到空区域而困惑。即使不需要描述,也应输出简单说明或至少保持回调函数存在。

// 错误:回调函数为空
function myplugin_empty_callback() {
    // 什么都没有
}

// 正确:至少输出一个简单的段落
function myplugin_proper_callback() {
    echo '<p>请配置以下选项:</p>';
}

页面slug不匹配

add_settings_section$page参数必须与add_options_page(或其他添加页面的函数)使用的slug完全一致,包括大小写。

// 添加页面时使用这个slug
add_options_page('标题', '菜单', '权限', 'my-plugin-page', 'callback');

// 错误:slug不一致(多了一个连字符)
add_settings_section('section_id', '标题', 'callback', 'my--plugin-page');

// 错误:大小写不一致
add_settings_section('section_id', '标题', 'callback', 'My-Plugin-Page');

// 正确:完全匹配
add_settings_section('section_id', '标题', 'callback', 'my-plugin-page');

在错误的钩子中注册

add_settings_section必须在admin_init钩子或更早的钩子中调用,如果在admin_menu之后调用可能无法正确显示。

// 错误:在admin_menu的回调函数中直接调用(可能太晚)
add_action('admin_menu', function() {
    add_options_page(...);
    add_settings_section(...); // 可能不会显示
});

// 正确:使用admin_init钩子
add_action('admin_menu', 'add_my_page');
add_action('admin_init', 'add_my_sections'); // 分开注册

最佳实践

使用唯一前缀避免冲突

为所有ID、选项名、页面slug添加唯一前缀,通常使用插件/主题的缩写或全名,用下划线连接。

// 使用插件唯一标识作为前缀
define('MYPLUGIN_PREFIX', 'myplugin_');

add_settings_section(
    MYPLUGIN_PREFIX . 'general_section',  // myplugin_general_section
    '常规设置',
    'myplugin_general_callback',
    MYPLUGIN_PREFIX . 'settings_page'     // myplugin_settings_page
);

编写清晰的区域描述回调

描述应简洁明了,指导用户操作,可包含HTML格式但避免复杂样式。对于需要转义的内容,使用相应的转义函数。

function myplugin_section_callback() {
    ?>
    <div class="notice notice-info inline">
        <p><strong>重要:</strong>这些设置影响网站前台显示。</p>
        <p>如需帮助,请参考我们的
            <a href="<?php echo esc_url('https://example.com/help'); ?>" target="_blank">
                帮助文档
            </a>
        </p>
    </div>
    <?php
}

遵循标准的代码组织模式

将相关设置组织在一起,提高代码可读性和维护性:

class MyPlugin_Settings {
    const PAGE_SLUG = 'myplugin_settings';

    public function init() {
        add_action('admin_init', [$this, 'register_sections']);
        add_action('admin_menu', [$this, 'add_menu_page']);
    }

    public function add_menu_page() {
        add_options_page(...);
    }

    public function register_sections() {
        // 基础设置区域
        add_settings_section(
            'basic',
            '基础配置',
            [$this, 'render_basic_section'],
            self::PAGE_SLUG
        );

        // 高级设置区域
        add_settings_section(
            'advanced',
            '高级功能',
            [$this, 'render_advanced_section'],
            self::PAGE_SLUG
        );
    }

    public function render_basic_section() {
        echo '<p>配置插件的基本功能。</p>';
    }

    public function render_advanced_section() {
        echo '<p>这些设置仅供高级用户使用。</p>';
    }
}

// 初始化
$settings = new MyPlugin_Settings();
$settings->init();

考虑可访问性(Accessibility)

为区域添加适当的ARIA属性,帮助屏幕阅读器用户理解页面结构:

function myplugin_accessible_section_callback() {
    ?>
    <div id="myplugin-settings-description" class="screen-reader-text">
        此区域包含所有基础设置选项,请按Tab键在不同字段间切换。
    </div>
    <p aria-describedby="myplugin-settings-description">
        配置以下选项以定制插件行为:
    </p>
    <?php
}

与设置字段保持逻辑关联

确保区域内的字段在逻辑上属于同一组,避免将不相关的设置放在同一区域。如果设置较多,考虑使用多个标签页而非单个页面内的多个区域。

// 良好的逻辑分组
add_settings_section(
    'myplugin_display_section',
    '显示设置',
    'callback_display',  // 包含字体、颜色、布局相关说明
    'page'
);
// 在此区域只添加显示相关的字段

add_settings_section(
    'myplugin_function_section',
    '功能设置',
    'callback_function',  // 包含功能开关、行为相关说明
    'page'
);
// 在此区域只添加功能相关的字段