wordpress主题:主题自定义设置

如何开发 wordpress 主题自定义设置功能

首页我们需要了解四个类型:

  1. Panels: 包含Sections,允许把多个Sections组合在一起
  2. Sections: 包含Controls, 每个Section可以包含多个Controls
  3. Settings: 将Controls于数据库中保存的设置相关联
  4. Controls: UI控件,通常控件包括输入框、选择框、下拉框、图片选择、日期选择等等,还可以自行扩展其他控件

1. 注册一个自定义函数

增加任何功能到自定义功能,需要用到的 customize_register,这个钩子访问一个WP_Customize_Manager的实例$wp_customize,增加的Panels、Sections、Settings、Controls 都需要在这个函数钩子内

/**
 * Add our Customizer content
 */
function mytheme_customize_register( $wp_customize ) {
   // Add all your Customizer content (i.e. Panels, Sections, Settings & Controls) here...
);
add_action( 'customize_register', 'mytheme_customize_register');

2. 增加一个Panels

Panels允许你包含多个 Sections,但是 Sections 不必在 Panels 下。一个 Panels 必须包含一个 Sections,一个 Sections 必须包含一个 Controls,才能显示。如果你增加 Panels,在页面没有显示,那得检查一下是否有 Sections, Sections 里是否 Controls.

用法

add_panel( $id, $args );

参数

$id字符串必须一个唯一的id, 默认:None
$args数组必须

$args 的参数

title字符串可选显示的名称
description字符串可选描述
priority数字可选排序
capability字符串可选根据用户的权限控制是否显示,默认:edit_theme_options
theme_supports字符串可选根据主题的设置是否显示,用到方法 add_theme_support
active_callback字符串可选根据当前页面是否显示,例如'active_callback' => 'is_front_page'
/**
 * Add our Header & Navigation Panel
 */
 $wp_customize->add_panel( 'header_naviation_panel',
   array(
      'title' => __( 'Header & Navigation' ),
      'description' => esc_html__( 'Adjust your Header and Navigation sections.' ), // Include html tags such as 
      'priority' => 160, // Not typically needed. Default is 160
      'capability' => 'edit_theme_options', // Not typically needed. Default is edit_theme_options
      'theme_supports' => '', // Rarely needed
      'active_callback' => '', // Rarely needed
   )
);
如果你想改变默认Panels或Sections的排序,可以参考下表
TitleIDPriority (Order)
Site Title & Taglinetitle_tagline20
Colorscolors40
Header Imageheader_image60
Background Imagebackground_image80
Menus (Panel)nav_menus100
Widgets (Panel)widgets110
Static Front Pagestatic_front_page120
default160
Additional CSScustom_css200

3. 增加一个Sections

Sections 是存放多个 Controls 的,Sections 可以放在 Panels 下,但不是必须的,多数时候都不用。

用法

add_section( $id, $args );

参数

$id字符串必须一个唯一的id, 默认:None
$args数组必须

$args 的参数

title字符串可选显示的名称
description字符串可选描述
panel字符串可选在哪个Panel下
priority数字可选排序
capability字符串可选根据用户的权限控制是否显示,默认:edit_theme_options
theme_supports字符串可选根据主题的设置是否显示,用到方法 add_theme_support
active_callback字符串可选根据当前页面是否显示,例如 'active_callback' => 'is_front_page'
description_hidden布尔值可选是否隐藏在帮助图标后面,默认:false
/**
 * Add our Sample Section
 */
$wp_customize->add_section( 'sample_custom_controls_section',
   array(
      'title' => __( 'Sample Custom Controls' ),
      'description' => esc_html__( 'These are an example of Customizer Custom Controls.' ),
      'panel' => '', // Only needed if adding your Section to a Panel
      'priority' => 160, // Not typically needed. Default is 160
      'capability' => 'edit_theme_options', // Not typically needed. Default is edit_theme_options
      'theme_supports' => '', // Rarely needed
      'active_callback' => '', // Rarely needed
      'description_hidden' => 'false', // Rarely needed. Default is False
   )
);

4. 增加Setting

Setting 和 Control 是搭配在一起的,每一个Control都需要一个 Setting.Setting 处理自定义程序对象的预览、保存和清理。

用法

add_setting( $id, $args );

参数

$id字符串必须一个唯一的id, 默认:None
$args数组必须

$args 的参数

default字符串可选相关联 Controller 的默认值
transport字符串可选更新预览的方式,默认:refresh
type字符串可选保存的方式,默认:theme_mod
capability字符串可选根据用户的权限控制是否显示,默认:edit_theme_options
theme_supports字符串可选根据主题的设置是否显示,用到方法 add_theme_support
validate_callback字符串可选验证设置的方法名称
sanitize_callback字符串可选保存到数据库前调用清理方法名称
sanitize_js_callback字符串可选在输出 js 代码前调用的方法名称
dirty字符串可选很少用,创建时不管是否有脏数据,默认:false
$wp_customize->add_setting( 'sample_default_text',
   array(
      'default' => '', // Optional.
      'transport' => 'refresh', // Optional. 'refresh' or 'postMessage'. Default: 'refresh'
      'type' => 'theme_mod', // Optional. 'theme_mod' or 'option'. Default: 'theme_mod'
      'capability' => 'edit_theme_options', // Optional. Default: 'edit_theme_options'
      'theme_supports' => '', // Optional. Rarely needed
      'validate_callback' => '', // Optional. The name of the function that will be called to validate Customizer settings
      'sanitize_callback' => '', // Optional. The name of the function that will be called to sanitize the input data before saving it to the database
      'sanitize_js_callback' => '', // Optional. The name of the function that will be called to sanitize the data before outputting to javascript code. Basically to_json.
      'dirty' => false, // Optional. Rarely needed. Whether or not the setting is initially dirty when created. Default: False
   )
);

type有两种设置方式,一种是 option ,另外一种是 theme_mod。option 指的是站点设置,无论是哪个主题都有影响;theme_mod 指的是特定主题的特定设置,大多数主题用这个。
尽管 sanitize_callback 参数是可选的,如果你提交到 wordpress 主题目录,官方插件 Theme Check plugin 会发出警告,add_setting 必须指定一个 sanitize_callback 函数。

5. 增加 Control

Control 是显示 UI 组件,在默认的 wordpress 核心代码中,已经提供了一些默认组件(输入框,选择框,单选按钮等等)。其他 Conrol 需要继承 WP_Customize_Control创建自己 Controls.

下面介绍几个常用的 Control:

  1. input Control 单行文本控件
  2. Checkbox Control 多选控件
  3. Select Control 下拉选择控件
  4. Radio Button Control 单选控件
  5. Dropdown Pages Control 下拉页面选择控件
  6. Textarea Control 多行控件
  7. Color Control 颜色控件
  8. Media Control 媒体控件
  9. Image Control 图片控件
  10. Cropped Image Control 图片裁剪控件
  11. Date Time Control 日期时间控件

5.1 Input Control

用法
add_control( $id, $args );
参数
$id字符串必须一个唯一的id, 默认:None
$args数组必须
$args 参数
label字符串可选显示的名称
description字符串可选描述
section字符串必须属于哪个 Section
priority数字可选排序;默认:10
type字符串必须控件类型,可以选择text, email, url, number, hidden or date. 默认:text
capability字符串可选根据用户的权限控制是否显示,默认:edit_theme_options
input_attrs数组可选输出一组控件属性,只能用于 textarea 和 input 类型
$wp_customize->add_setting( 'sample_default_text',
   array(
      'default' => '',
      'transport' => 'refresh',
      'sanitize_callback' => 'skyrocket_text_sanitization'
   )
);
$wp_customize->add_control( 'sample_default_text',
   array(
      'label' => __( 'Default Text Control' ),
      'description' => esc_html__( 'Text controls Type can be either text, email, url, number, hidden, or date' ),
      'section' => 'default_controls_section',
      'priority' => 10, // Optional. Order priority to load the control. Default: 10
      'type' => 'text', // Can be either text, email, url, number, hidden, or date
      'capability' => 'edit_theme_options', // Optional. Default: 'edit_theme_options'
      'input_attrs' => array( // Optional.
         'class' => 'my-custom-class',
         'style' => 'border: 1px solid rebeccapurple',
         'placeholder' => __( 'Enter name...' ),
      ),
   )
);

5.2 Checkbox Control

用法
add_control( $id, $args );
参数
$id字符串必须一个唯一的id, 默认:None
$args数组必须
$args 参数
label字符串可选显示的名称
description字符串可选描述
section字符串必须属于哪个 Section
priority数字可选排序;默认:10
type字符串必须checkbox
capability字符串可选根据用户的权限控制是否显示,默认:edit_theme_options
$wp_customize->add_setting( 'sample_default_checkbox',
   array(
      'default' => 0,
      'transport' => 'refresh',
      'sanitize_callback' => 'skyrocket_switch_sanitization'
   )
);
$wp_customize->add_control( 'sample_default_checkbox',
   array(
      'label' => __( 'Default Checkbox Control', 'ephemeris' ),
      'description' => esc_html__( 'Sample description' ),
      'section'  => 'default_controls_section',
      'priority' => 10, // Optional. Order priority to load the control. Default: 10
      'type'=> 'checkbox',
      'capability' => 'edit_theme_options', // Optional. Default: 'edit_theme_options'
   )
);

5.3 Select Control

用法
add_control( $id, $args );
参数
$id字符串必须一个唯一的id, 默认:None
$args数组必须
$args 参数
label字符串可选显示的名称
description字符串可选描述
section字符串必须属于哪个 Section
priority数字可选排序;默认:10
type字符串必须select
capability字符串可选根据用户的权限控制是否显示,默认:edit_theme_options
choices数组可选一组选项,只用于 radio 和 select 类型
$wp_customize->add_setting( 'sample_default_select',
   array(
      'default' => 'jet-fuel',
      'transport' => 'refresh',
      'sanitize_callback' => 'skyrocket_radio_sanitization'
   )
);
$wp_customize->add_control( 'sample_default_select',
   array(
      'label' => __( 'Standard Select Control' ),
      'description' => esc_html__( 'Sample description' ),
      'section' => 'default_controls_section',
      'priority' => 10, // Optional. Order priority to load the control. Default: 10
      'type' => 'select',
      'capability' => 'edit_theme_options', // Optional. Default: 'edit_theme_options'
      'choices' => array( // Optional.
         'wordpress' => __( 'WordPress' ),
         'hamsters' => __( 'Hamsters' ),
         'jet-fuel' => __( 'Jet Fuel' ),
         'nuclear-energy' => __( 'Nuclear Energy' )
      )
   )
);

5.4 Radio Button Control

用法
add_control( $id, $args );
参数
$id字符串必须一个唯一的id, 默认:None
$args数组必须
$args 参数
label字符串可选显示的名称
description字符串可选描述
section字符串必须属于哪个 Section
priority数字可选排序;默认:10
type字符串必须radio
capability字符串可选根据用户的权限控制是否显示,默认:edit_theme_options
choices数组可选一组选项,只用于 radio 和 select 类型
$wp_customize->add_setting( 'sample_default_radio',
   array(
      'default' => 'spider-man',
      'transport' => 'refresh',
      'sanitize_callback' => 'skyrocket_radio_sanitization'
   )
);
$wp_customize->add_control( 'sample_default_radio',
   array(
      'label' => __('Standard Radio Control'),
      'description' => esc_html__('Sample description'),
      'section' => 'default_controls_section',
      'priority' => 10, // Optional. Order priority to load the control. Default: 10
      'type' => 'radio',
      'capability' => 'edit_theme_options', // Optional. Default: 'edit_theme_options'
      'choices' => array( // Optional.
         'captain-america' => __('Captain America'),
         'iron-man' => __('Iron Man'),
         'spider-man' => __('Spider-Man'),
         'thor' => __('Thor')
      )
   )
);

5.5 Dropdown Pages Control

用法
add_control( $id, $args );
参数
$id字符串必须一个唯一的id, 默认:None
$args数组必须
$args 参数
label字符串可选显示的名称
description字符串可选描述
section字符串必须属于哪个 Section
priority数字可选排序;默认:10
type字符串必须dropdown-pages
capability字符串可选根据用户的权限控制是否显示,默认:edit_theme_options
$wp_customize->add_setting('sample_default_dropdownpages',
   array(
      'default' => '1548',
      'transport' => 'refresh',
      'sanitize_callback' => 'absint'
   )
);
$wp_customize->add_control('sample_default_dropdownpages',
   array(
      'label' => __('Default Dropdown Pages Control' ),
      'description' => esc_html__('Sample description' ),
      'section' => 'default_controls_section',
      'priority' => 10, // Optional. Order priority to load the control. Default: 10
      'type' => 'dropdown-pages',
      'capability' => 'edit_theme_options', // Optional. Default: 'edit_theme_options'
   )
);

5.6 Textarea Control

用法
add_control( $id, $args );
参数
$id字符串必须一个唯一的id, 默认:None
$args数组必须
$args 参数
label字符串可选显示的名称
description字符串可选描述
section字符串必须属于哪个 Section
priority数字可选排序;默认:10
type字符串必须textarea
capability字符串可选根据用户的权限控制是否显示,默认:edit_theme_options
input_attrs数组可选输出一组控件属性,只能用于 textarea 和 input 类型
$wp_customize->add_setting( 'sample_default_textarea',
   array(
      'default' => '',
      'transport' => 'refresh',
      'sanitize_callback' => 'wp_filter_nohtml_kses'
   )
);
$wp_customize->add_control( 'sample_default_textarea',
   array(
      'label' => __( 'Default Textarea Control' ),
      'description' => esc_html__( 'Sample description' ),
      'section' => 'default_controls_section',
      'priority' => 10, // Optional. Order priority to load the control. Default: 10
      'type' => 'textarea',
      'capability' => 'edit_theme_options', // Optional. Default: 'edit_theme_options'
      'input_attrs' => array( // Optional.
         'class' => 'my-custom-class',
         'style' => 'border: 1px solid #999',
         'placeholder' => __( 'Enter message...' ),
      ),
   )
);

5.7 Color Control

用法
add_control( $id, $args );
参数
$id字符串必须一个唯一的id, 默认:None
$args数组必须
$args 参数
label字符串可选显示的名称
description字符串可选描述
section字符串必须属于哪个 Section
priority数字可选排序;默认:10
capability字符串可选根据用户的权限控制是否显示,默认:edit_theme_options
$wp_customize->add_setting('sample_default_color',
   array(
      'default' => '',
      'transport' => 'refresh',
   )
);
$wp_customize->add_control(new WP_Customize_Color_Control( $wp_customize, 'sample_default_color',
   array(
      'label' => __( 'Default Media Control' ),
      'description' => esc_html__( 'This is the description for the Media Control' ),
      'section' => 'default_controls_section',
   )
));

5.8 Media Control

用法
add_control( $id, $args );
参数
$id字符串必须一个唯一的id, 默认:None
$args数组必须
$args 参数
label字符串可选显示的名称
description字符串可选描述
section字符串必须属于哪个 Section
priority数字可选排序;默认:10
mime_type文件可选文件类型,可以选择image, audio, video, application, text
button_labels字符串可选控件的属性
$wp_customize->add_setting( 'sample_default_media',
   array(
      'default' => '',
      'transport' => 'refresh',
      'sanitize_callback' => 'absint'
   )
);
$wp_customize->add_control(new WP_Customize_Media_Control( $wp_customize, 'sample_default_media',
   array(
      'label' => __( 'Default Media Control' ),
      'description' => esc_html__( 'This is the description for the Media Control' ),
      'section' => 'default_controls_section',
      'mime_type' => 'image',  // Required. Can be image, audio, video, application, text
      'button_labels' => array( // Optional
         'select' => __( 'Select File' ),
         'change' => __( 'Change File' ),
         'default' => __( 'Default' ),
         'remove' => __( 'Remove' ),
         'placeholder' => __( 'No file selected' ),
         'frame_title' => __( 'Select File' ),
         'frame_button' => __( 'Choose File' ),
      )
   )
));

5.9 Image Control

用法
add_control( $id, $args );
参数
$id字符串必须一个唯一的id, 默认:None
$args数组必须
$args 参数
label字符串可选显示的名称
description字符串可选描述
section字符串必须属于哪个 Section
priority数字可选排序;默认:10
button_labels字符串可选控件的属性
$wp_customize->add_setting( 'sample_default_image',
   array(
      'default' => '',
      'transport' => 'refresh',
   )
);
$wp_customize->add_control( new WP_Customize_Image_Control( $wp_customize, 'sample_default_image',
   array(
      'label' => __( 'Default Image Control' ),
      'description' => esc_html__( 'This is the description for the Image Control' ),
      'section' => 'default_controls_section',
      'button_labels' => array( // Optional.
         'select' => __( 'Select Image' ),
         'change' => __( 'Change Image' ),
         'remove' => __( 'Remove' ),
         'default' => __( 'Default' ),
         'placeholder' => __( 'No image selected' ),
         'frame_title' => __( 'Select Image' ),
         'frame_button' => __( 'Choose Image' ),
      )
   )
));

5.10 Cropped Image Control

用法
add_control( $id, $args );
参数
$id字符串必须一个唯一的id, 默认:None
$args数组必须
$args 参数
label字符串可选显示的名称
description字符串可选描述
section字符串必须属于哪个 Section
flex_width布尔值可选度是否自适应,默认:false
flex_height布尔值可选高度是否自适应,默认:false
width数字可选建议裁剪的宽度,默认:150
height数字可选建议裁剪的高度,默认:150
button_labels数组可选控件的属性
$wp_customize->add_setting( 'sample_default_cropped_image',
   array(
      'default' => '',
      'transport' => 'refresh',
   )
);
$wp_customize->add_control( new WP_Customize_Cropped_Image_Control( $wp_customize, 'sample_default_cropped_image',
   array(
      'label' => __( 'Default Cropped Image Control' ),
      'description' => esc_html__( 'This is the description for the Cropped Image Control' ),
      'section' => 'default_controls_section',
      'flex_width' => false, // Optional. Default: false
      'flex_height' => true, // Optional. Default: false
      'width' => 800, // Optional. Default: 150
      'height' => 400, // Optional. Default: 150
      'button_labels' => array( // Optional.
         'select' => __( 'Select Image' ),
         'change' => __( 'Change Image' ),
         'remove' => __( 'Remove' ),
         'default' => __( 'Default' ),
         'placeholder' => __( 'No image selected' ),
         'frame_title' => __( 'Select Image' ),
         'frame_button' => __( 'Choose Image' ),
      )
   )
));

5.11 Date Time Control

用法
add_control( $id, $args );
参数
$id字符串必须一个唯一的id, 默认:None
$args数组必须
$args 参数
label字符串可选显示的名称
description字符串可选描述
section字符串必须属于哪个 Section
include_time布尔值可选是否显示时间字段,默认:true
allow_past_date布尔值可选是否显示时间字段,默认:true
twelve_hour_format布尔值可选12小时制还是24小时制,默认:true (12小时制)
min_year数字可选允许的最小年份,默认:1000
max_year数字可选允许的最大年份,默认:9999
$wp_customize->add_setting( 'sample_date_time',
   array(
      'default' => '2020-08-28 16:30:00',
      'transport' => 'refresh',
      'sanitize_callback' => 'skyrocket_date_time_sanitization'
   )
);
$wp_customize->add_control( new WP_Customize_Date_Time_Control( $wp_customize, 'sample_date_time',
   array(
      'label' => __( 'Default Date Control' ),
      'description' => esc_html__( 'This is the Date Time Control. It also has Max and Min years set.' ),
      'section' => 'default_controls_section',
      'include_time' => true, // Optional. Default: true
      'allow_past_date' => true, // Optional. Default: true
      'twelve_hour_format' => true, // Optional. Default: true
      'min_year' => '2010', // Optional. Default: 1000
      'max_year' => '2025' // Optional. Default: 9999
   )
));

6. 数据处理

永远不要相信用户输入的数据,对于用户的输入需要处理才存入数据库,wordpress 内容了一些处理函数 Built-in WordPress Functions
在 Setting 中有 validate_callback 和 sanitize_callback回调方法过滤和处理用户输入,可以用 wordpress 自带的函数,也可以自定义函数。

// 处理html标签,用wordpress自带的函数wp_filter_nohtml_kses()
$wp_customize->add_setting( 'sample_default_text',
   array(
      'default' => __( 'This is some default text' ),
      'sanitize_callback' => 'wp_filter_nohtml_kses',
   )
);

// 验证email,用wordpress自带的函数sanitize_email()
$wp_customize->add_setting( 'sample_default_text',
   array(
      'default' => __( 'This is some default text' ),
      'sanitize_callback' => 'sanitize_email',
   )
);

// 验证多选框,用自定义函数
function mytheme_chkbox_sanitization( $input ) {
   if ( true === $input ) {
      return 1;
   } else {
      return 0;
   }
}

$wp_customize->add_setting( 'sample_default_checkbox',
   array(
      'default' => 0,
      'sanitize_callback' => 'mytheme_chkbox_sanitization',
   )
);

7. 增加 Control 到已存在 Section

wordpress 默认存在几个 Section,如果我们想要在默认的 Section 中新增 Control. 只要把 section 设置为已存在的 Section 的 id 即可

// 增加一个select Control 到 Head Image Section
$wp_customize->add_setting( 'my_new_header_image_select',
   array(
      'default' => __( 'center' ),
      'sanitize_callback' => 'sanitize_text_field',
   )
);
$wp_customize->add_control( 'my_new_header_image_select',
   array(
      'label' => __( 'Header Image Alignment' ),
      'section' => 'header_image', // 添加到Section
      'type' => 'select',
      'choices' => array(
         'left' => 'Left',
         'center' => 'Center',
         'right' => 'Right',
      )
   )
);

8. 刷新预览

在用户输入更新数据,有两种预览方式,一种是刷新整个页面,另一种事局部刷新。控制的参数事 transport,默认的事全局刷新 refresh,局部刷新 postMessage。

$wp_customize->add_setting( 'sample_default_text',
   array(
      'default' => '',
      'transport' => 'refresh' // 全局刷新,postMessage局部刷新
   )
);

8.1 用 php 实现局部刷新

用 php 实现局部刷新,需要注册一个 Partial

用法
add_partial( $id, $args );
参数
$id字符串必须一个唯一的id, 默认:None
$args数组必须
$args 参数
selector字符串必须ui 关联的选择器,编辑的快捷方式也是基于此
container_inclusive布尔值可选如果true,将刷新整个容器;如果false,则刷新容器的子容器。默认:false
render_callback字符串必须生成要在刷新时呈现的标记
fallback_refresh布尔值可选如果在文档中找不到部分,是否应该进行整页刷新。默认:true
capability布尔值可选根据用户的权限控制是否显示,通常是来自 Setting 的功能
$wp_customize->selective_refresh->add_partial( 'social_urls',
   array(
      'selector' => '.social-header',
      'container_inclusive' => false,
      'render_callback' => function() {
         echo mytheme_get_social_media_icons();
      },
      'fallback_refresh' => true
   )
);

当注册一个add_partial(),选择的容器将得到一个编辑的快捷方式,点击即可定位可编辑的地方。可以通过 js 的方式实现局部刷新,这里不细说。

9. 获取自定义的值

设置之后,需要把值用到模板中,需要用到函数 get_theme_mod()

用法
get_theme_mod( $id, $default );
参数
$id字符串必须Setting 设置的 id
$default字符串/布尔值可选 如果没有值的时候,默认显示
<?php echo get_theme_mod( 'background_color', '#fff' ); ?>

这个例子将得到background_color的值并输出,如果没有值,将会输出#fff

10.总结

这就是 wordpress 自定义主题功能的使用方法,但这只是通常用到的,更多功能可以查看wordpress的源码,在 /wp-includes/customizer 文件夹下。推荐一个好看的自定义功能框架 https://kirki.org/

下一篇