# 8.1 简介

选项 API 向 {$wpdb->prefix}_options 数据库表中添加命名选项/值对的安全方法。如果该选项已经存在,则它将不执行任何操作。保存选项后,可以使用 get_option() 访问它,使用update_option() 更改它,使用 delete_option() 删除它。

不需要序列化值。如果需要序列化该值,则在将其插入数据库之前将对其进行序列化。可以创建不带值的选项,然后在以后添加值。

调用 add_option 首先检查选项是否已添加,如果存在同名选项,则返回 false。接下来,它检查以确保选项名不是受保护的名称 alloptions 或 otoptions 之一,如果试图覆盖受保护的选项,则会出现错误消息。如果选项名称不受保护,并且不存在,则将创建该选项。

注意:add_option 使用 get_option 来确定该选项是否已经存在,并且由于 get_option 返回false作为默认值,如果在数据库中将选项设置为false(例如,通过update_option($option_name,false) ,则后续的add_option调用将更改该值,因为它似乎会添加一个选项,即该选项不存在。

# 选项在什么地方保存?

选项存储在 {$wpdb->prefix}_options 数据表中。$wpdb->prefix 由 wp-config.php 配置文件中的 $table_prefix 变量定义。

# 8.2 使用选项 API

选项可以以单个值或者数组的形式存储在 WordPress 数据库中。

  • 单个值

保存为单个值的时候,选项值为单个字符串、整数等。

<?php
// 添加一个新的选项
add_option('mla_custom_option', 'hello world!');
// 获取选项
$option = get_option('mla_custom_option');

1
2
3
4
5
6
  • 数组

保存为数组时,选项值为一个数组。

<?php
// 选项数组
$data_r = ['title' => 'hello world!', 1, false];
// 添加一个新的选项
add_option('mla_custom_option', $data_r);
// 获取选项数组
$options_r = get_option('mla_custom_option');
// 获取键值为 title 的值
echo esc_html($options_r['title']);
1
2
3
4
5
6
7
8
9

如果我们需要保存大量选项,把这些选项保存为数组,对性能提升可能会有帮助。

在数据库中 mla_custom_option 的值被序列化为

a:3:{s:5:"title";s:12:"hello world!";i:0;i:1;i:1;b:0;}
1

序列化处理是 WordPress 的强项,比如在使用 update_option 的时候,可以把字符串,数组,或者对象直接存进去,WordPress 会自定化进行序列化处理,需要用到的时候,只需要使用 get_option 函数取出数据即可,原本是数组,取出来还是数组,原来是对象,取出来依然是对象,非常方便。

WordPress 是怎么做到的呢?这个就是 WordPress 自己定义了几个序列化处理的相关函数把序列化处理过程做的更简单:

maybe_unserialize 和 maybe_serialize 函数

首先 WordPress 扩展了 PHP 原生的 unserialize 和 serialize 函数,定义了 maybe_unserialize 和 maybe_serialize 函数。

<?php
// 反序列化
maybe_unserialize( $original );
// 序列化
maybe_serialize( $data );
1
2
3
4
5

maybe_unserialize 是 WordPress 的反序列化函数,意思是它会首先会检测一下当前的字符串是不是序列化之后的字符串,是的话,它才使用 PHP 的 unserialize 函数进行反序列化,如果不是,则直接返回。

maybe_serialize 是 WordPress 的序列化函数,如果是普通字符串,则直接返回,如果 $data 是对象或者数组,则是用 PHP serialize 函数对齐进行序列化。特别需要注意的是,如果 $data 是已经序列化的字符串,它还会对其再进行一次序列化操作。下面的例子比较全面解释其用法:

<?php
// 字符串不做任何处理,直接返回。
$data = 'Hello World!';
echo maybe_serialize( $data );
// Hello World!

// 整形,浮点型,和布尔型数据也是不做处理,直接返回。
$data = 55;
echo maybe_serialize( $data );
// 55

$data = 4.560
echo maybe_serialize( $data );
// 4.560

$data = true;
$data = maybe_serialize( $data );
// $data = true;

$data = null;
$data = maybe_serialize( $data );
// $data = null

// 对象和数组会被转换成序列化数据
$data = array( 1 => 'Hello World!', 'foo' => 'bar' );
echo maybe_serialize( $data );
// a:2:{i:1;s:12:"Hello World!";s:3:"foo";s:3:"bar";}

// 已经序列化的字符串,会被再次序列化
$data = 'a:2:{i:1;s:12:"Hello World!";s:3:"foo";s:3:"bar";}';
echo maybe_serialize( $data );
// s:50:"a:2:{i:1;s:12:"Hello World!";s:3:"foo";s:3:"bar";}";
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# 函数参考

添加选项 获取选项 更新选项 删除选项
add_option()
add_site_option()
get_option()
get_site_option()
update_option()
update_site_option()
delete_option()
delete_site_option()

# 8.3 自定义设置页面

创建自定义设置页面需要用到 创建管理菜单,使用 设置 API选项 API 中的相关知识。

# 创建自定义设置页面的完整示例

下面是创建自定义设置页面的一个完整示例,以下代码中,我们添加一个名为 “MLA测试” 的顶级菜单,注册了一个名为 mla_options 的选项,并使用设置 API和选项 API执行了一个CDUR 增删改查操作(包含显示错误/更新消息)

<?php

/**
 * 自定义选项和设置
 */
function mla_settings_init() {
   // 为 mla 页面注册新设置
   register_setting( 'mla', 'mla_options' );

   // 在 mla 页面上注册新分节 mla_section_developers
   add_settings_section(
      'mla_section_developers',
      __( 'The Matrix has you.', 'mla' ),
      'mla_section_developers_cb',
      'mla'
   );

   // 在 mla 页面中,在 mla_section_developers 分节上注册新设置 mla_field_pill
   add_settings_field(
      'mla_field_pill', // 此值仅在内部使用
      __( 'Pill', 'mla' ),
      'mla_field_pill_cb',
      'mla',
      'mla_section_developers',
      [
         'label_for'         => 'mla_field_pill',
         'class'             => 'mla_row',
         'mla_custom_data' => 'custom',
      ]
   );
}

/**
 *  注册 mla_settings_init 到 admin_init Action 钩子
 */
add_action( 'admin_init', 'mla_settings_init' );

/**
 * 自定义选项和设置:
 * 回调函数
 */

// developers 分节回调

// 分节回调 可以接受一个 $args 参数,它是一个数组。
// $args 定义了以下键: title, id, callback.
// 这些值在 add_settings_section() 函数中定义.
function mla_section_developers_cb( $args ) {
   ?>
    <p id=<?php echo esc_attr( $args[ 'id' ] ); ?>><?php esc_html_e( 'Follow the white rabbit.', 'mla' ); ?></p>
   <?php
}

// pill 字段回调函数

// 字段回调可以接受一个 $args 参数,它是一个数组。
// $args 在 add_settings_section() 函数中定义。
// WordPress 与以下键进行了神奇的交互:label_for,class。
// label_for 键值是用于 <label> 标签的属性。
// class 键值适用于 包含在字段里的 <tr> 标签的类属性 。
// 你可以在回调中添加要自定义键值对。
function mla_field_pill_cb( $args ) {
   // 获取我们在 register_setting() 注册的设置值 
   $options = get_option( 'mla_options' );
   // 输出字段
   ?>
    <select id=<?php echo esc_attr( $args[ 'label_for' ] ); ?>
            data-custom=<?php echo esc_attr( $args[ 'mla_custom_data' ] ); ?>
            name=mla_options[<?php echo esc_attr( $args[ 'label_for' ] ); ?>]
    >
        <option value=red <?php echo isset( $options[ $args[ 'label_for' ] ] ) ? ( selected( $options[ $args[ 'label_for' ] ], 'red', false ) ) : ( '' ); ?>>
         <?php esc_html_e( 'red pill', 'mla' ); ?>
        </option>
        <option value=blue <?php echo isset( $options[ $args[ 'label_for' ] ] ) ? ( selected( $options[ $args[ 'label_for' ] ], 'blue', false ) ) : ( '' ); ?>>
         <?php esc_html_e( 'blue pill', 'mla' ); ?>
        </option>
    </select>
    <p class=description>
      <?php esc_html_e( 'You take the blue pill and the story ends. You wake in your bed and you believe whatever you want to believe.', 'mla' ); ?>
    </p>
    <p class=description>
      <?php esc_html_e( 'You take the red pill and you stay in Wonderland and I show you how deep the rabbit-hole goes.', 'mla' ); ?>
    </p>
   <?php
}

/**
 * 顶级菜单
 */
function mla_options_page() {
   // 添加顶级菜单页面
   add_menu_page(
      'mla',
      'mla Options',
      'manage_options',
      'mla',
      'mla_options_page_html'
   );
}

/**
 * 在 admin_menu Action 钩子上面注册我们的 mla_options_page 页面
 */
add_action( 'admin_menu', 'mla_options_page' );

/**
 * 顶级菜单:
 * 回调函数
 */
function mla_options_page_html() {
   // 检查用户能力
   if ( ! current_user_can( 'manage_options' ) ) {
      return;
   }

   // 添加 错误/更新 信息
   // 检查用户是否已提交设置
   // WordPress 会将更新的设置 $_GET 参数添加到url
   if ( isset( $_GET[ 'settings-updated' ] ) ) {
      // 添加设置保存的消息,同时添加class updated
      add_settings_error( 'mla_messages', 'mla_message', __( 'Settings Saved', 'mla' ), 'updated' );
   }

   // 显示错误/更新消息
   settings_errors( 'mla_messages' );
   ?>
    <div class=wrap>
        <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
        <form action=options.php method=post>
         <?php
         // 输出已注册设置 mla 的安全字段
         settings_fields( 'mla' );
         // 输出设置节及其字段
         // (分节是给 mla 注册的,每个字段都注册到特定的分节)
         do_settings_sections( 'mla' );
         // 输出保存设置按钮
         submit_button( 'Save Settings' );
         ?>
        </form>
    </div>
   <?php
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143